From 9e6e0dc11a0322523008046f6af890544d2463f5 Mon Sep 17 00:00:00 2001 From: Dieter Adriaenssens Date: Sun, 2 May 2010 21:01:53 +0200 Subject: [PATCH] upgrade to PHPExcel 1.7.2 --- libraries/PHPExcel/PHPExcel.php | 65 +- libraries/PHPExcel/PHPExcel/Calculation.php | 791 ++++-- .../PHPExcel/Calculation/Exception.php | 8 +- .../PHPExcel/Calculation/ExceptionHandler.php | 8 +- .../PHPExcel/Calculation/FormulaParser.php | 8 +- .../PHPExcel/Calculation/FormulaToken.php | 8 +- .../PHPExcel/Calculation/Function.php | 8 +- .../PHPExcel/Calculation/Functions.php | 2335 ++++++++++++----- libraries/PHPExcel/PHPExcel/Cell.php | 78 +- .../PHPExcel/Cell/AdvancedValueBinder.php | 24 +- libraries/PHPExcel/PHPExcel/Cell/DataType.php | 48 +- .../PHPExcel/PHPExcel/Cell/DataValidation.php | 8 +- .../PHPExcel/Cell/DefaultValueBinder.php | 19 +- .../PHPExcel/PHPExcel/Cell/Hyperlink.php | 8 +- .../PHPExcel/PHPExcel/Cell/IValueBinder.php | 8 +- libraries/PHPExcel/PHPExcel/Comment.php | 39 +- .../PHPExcel/PHPExcel/DocumentProperties.php | 8 +- .../PHPExcel/PHPExcel/DocumentSecurity.php | 8 +- libraries/PHPExcel/PHPExcel/HashTable.php | 32 +- libraries/PHPExcel/PHPExcel/IComparable.php | 27 +- libraries/PHPExcel/PHPExcel/IOFactory.php | 110 +- libraries/PHPExcel/PHPExcel/NamedRange.php | 8 +- libraries/PHPExcel/PHPExcel/Reader/CSV.php | 59 +- .../PHPExcel/Reader/DefaultReadFilter.php | 8 +- .../PHPExcel/PHPExcel/Reader/Excel2003XML.php | 698 +++++ .../PHPExcel/PHPExcel/Reader/Excel2007.php | 1773 +++++++------ libraries/PHPExcel/PHPExcel/Reader/Excel5.php | 817 +++++- .../PHPExcel/Reader/Excel5/Escher.php | 8 +- .../PHPExcel/PHPExcel/Reader/IReadFilter.php | 8 +- .../PHPExcel/PHPExcel/Reader/IReader.php | 8 +- libraries/PHPExcel/PHPExcel/Reader/OOCalc.php | 500 ++++ libraries/PHPExcel/PHPExcel/Reader/SYLK.php | 506 ++++ .../PHPExcel/PHPExcel/Reader/Serialized.php | 8 +- .../PHPExcel/PHPExcel/ReferenceHelper.php | 260 +- libraries/PHPExcel/PHPExcel/RichText.php | 41 +- .../PHPExcel/RichText/ITextElement.php | 6 +- libraries/PHPExcel/PHPExcel/RichText/Run.php | 6 +- .../PHPExcel/RichText/TextElement.php | 6 +- libraries/PHPExcel/PHPExcel/Shared/Date.php | 17 +- .../PHPExcel/PHPExcel/Shared/Drawing.php | 90 +- libraries/PHPExcel/PHPExcel/Shared/Escher.php | 8 +- .../PHPExcel/Shared/Escher/DgContainer.php | 8 +- .../Escher/DgContainer/SpgrContainer.php | 8 +- .../DgContainer/SpgrContainer/SpContainer.php | 8 +- .../PHPExcel/Shared/Escher/DggContainer.php | 8 +- .../Escher/DggContainer/BstoreContainer.php | 8 +- .../DggContainer/BstoreContainer/BSE.php | 8 +- .../DggContainer/BstoreContainer/BSE/Blip.php | 8 +- libraries/PHPExcel/PHPExcel/Shared/Excel5.php | 36 +- libraries/PHPExcel/PHPExcel/Shared/File.php | 48 +- libraries/PHPExcel/PHPExcel/Shared/Font.php | 665 ++++- .../PHPExcel/PHPExcel/Shared/JAMA/Matrix.php | 87 +- .../Shared/OLE/ChainedBlockStream.php | 4 +- .../PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php | 2 +- .../PHPExcel/PHPExcel/Shared/OLERead.php | 6 +- libraries/PHPExcel/PHPExcel/Shared/PDF.php | 6 +- .../PHPExcel/Shared/PasswordHasher.php | 8 +- libraries/PHPExcel/PHPExcel/Shared/String.php | 135 +- .../PHPExcel/PHPExcel/Shared/XMLWriter.php | 8 +- .../PHPExcel/Shared/ZipStreamWrapper.php | 10 +- .../PHPExcel/Shared/trend/bestFitClass.php | 26 +- .../Shared/trend/exponentialBestFitClass.php | 18 +- .../Shared/trend/linearBestFitClass.php | 8 +- .../Shared/trend/logarithmicBestFitClass.php | 18 +- .../Shared/trend/polynomialBestFitClass.php | 8 +- .../Shared/trend/powerBestFitClass.php | 28 +- libraries/PHPExcel/PHPExcel/Style.php | 488 ++-- .../PHPExcel/PHPExcel/Style/Alignment.php | 61 +- libraries/PHPExcel/PHPExcel/Style/Border.php | 53 +- libraries/PHPExcel/PHPExcel/Style/Borders.php | 52 +- libraries/PHPExcel/PHPExcel/Style/Color.php | 53 +- .../PHPExcel/PHPExcel/Style/Conditional.php | 39 +- libraries/PHPExcel/PHPExcel/Style/Fill.php | 57 +- libraries/PHPExcel/PHPExcel/Style/Font.php | 67 +- .../PHPExcel/PHPExcel/Style/NumberFormat.php | 260 +- .../PHPExcel/PHPExcel/Style/Protection.php | 51 +- libraries/PHPExcel/PHPExcel/Worksheet.php | 492 ++-- .../PHPExcel/Worksheet/BaseDrawing.php | 39 +- .../PHPExcel/Worksheet/CellIterator.php | 41 +- .../PHPExcel/Worksheet/ColumnDimension.php | 45 +- .../PHPExcel/PHPExcel/Worksheet/Drawing.php | 39 +- .../PHPExcel/Worksheet/Drawing/Shadow.php | 39 +- .../PHPExcel/Worksheet/HeaderFooter.php | 10 +- .../Worksheet/HeaderFooterDrawing.php | 39 +- .../PHPExcel/Worksheet/MemoryDrawing.php | 39 +- .../PHPExcel/Worksheet/PageMargins.php | 8 +- .../PHPExcel/PHPExcel/Worksheet/PageSetup.php | 104 +- .../PHPExcel/Worksheet/Protection.php | 8 +- libraries/PHPExcel/PHPExcel/Worksheet/Row.php | 8 +- .../PHPExcel/Worksheet/RowDimension.php | 44 +- .../PHPExcel/Worksheet/RowIterator.php | 8 +- .../PHPExcel/PHPExcel/Worksheet/SheetView.php | 8 +- .../PHPExcel/PHPExcel/WorksheetIterator.php | 8 +- libraries/PHPExcel/PHPExcel/Writer/CSV.php | 8 +- .../PHPExcel/PHPExcel/Writer/Excel2007.php | 8 +- .../PHPExcel/Writer/Excel2007/Comments.php | 14 +- .../Writer/Excel2007/ContentTypes.php | 8 +- .../PHPExcel/Writer/Excel2007/DocProps.php | 8 +- .../PHPExcel/Writer/Excel2007/Drawing.php | 16 +- .../PHPExcel/Writer/Excel2007/Rels.php | 18 +- .../PHPExcel/Writer/Excel2007/StringTable.php | 18 +- .../PHPExcel/Writer/Excel2007/Style.php | 12 +- .../PHPExcel/Writer/Excel2007/Theme.php | 8 +- .../PHPExcel/Writer/Excel2007/Workbook.php | 29 +- .../PHPExcel/Writer/Excel2007/Worksheet.php | 201 +- .../PHPExcel/Writer/Excel2007/WriterPart.php | 8 +- libraries/PHPExcel/PHPExcel/Writer/Excel5.php | 54 +- .../PHPExcel/Writer/Excel5/BIFFwriter.php | 8 +- .../PHPExcel/Writer/Excel5/Escher.php | 12 +- .../PHPExcel/PHPExcel/Writer/Excel5/Font.php | 8 +- .../PHPExcel/Writer/Excel5/Parser.php | 102 +- .../PHPExcel/Writer/Excel5/Workbook.php | 134 +- .../PHPExcel/Writer/Excel5/Worksheet.php | 387 ++- .../PHPExcel/PHPExcel/Writer/Excel5/Xf.php | 31 +- libraries/PHPExcel/PHPExcel/Writer/HTML.php | 238 +- .../PHPExcel/PHPExcel/Writer/IWriter.php | 8 +- libraries/PHPExcel/PHPExcel/Writer/PDF.php | 19 +- .../PHPExcel/PHPExcel/Writer/Serialized.php | 12 +- 118 files changed, 9154 insertions(+), 4035 deletions(-) create mode 100644 libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php create mode 100644 libraries/PHPExcel/PHPExcel/Reader/OOCalc.php create mode 100644 libraries/PHPExcel/PHPExcel/Reader/SYLK.php diff --git a/libraries/PHPExcel/PHPExcel.php b/libraries/PHPExcel/PHPExcel.php index ac5f00246..a7ff765de 100644 --- a/libraries/PHPExcel/PHPExcel.php +++ b/libraries/PHPExcel/PHPExcel.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/WorksheetIterator.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel { @@ -212,6 +212,8 @@ class PHPExcel * Add sheet * * @param PHPExcel_Worksheet $pSheet + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @return PHPExcel_Worksheet * @throws Exception */ public function addSheet(PHPExcel_Worksheet $pSheet = null, $iSheetIndex = null) @@ -229,7 +231,14 @@ class PHPExcel 0, array($pSheet) ); + + // Adjust active sheet index if necessary + if ($this->_activeSheetIndex >= $iSheetIndex) { + ++$this->_activeSheetIndex; + } + } + return $pSheet; } /** @@ -390,10 +399,11 @@ class PHPExcel * Add external sheet * * @param PHPExcel_Worksheet $pSheet External sheet to add + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) * @throws Exception * @return PHPExcel_Worksheet */ - public function addExternalSheet(PHPExcel_Worksheet $pSheet) { + public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) { if (!is_null($this->getSheetByName($pSheet->getTitle()))) { throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first."); } @@ -414,7 +424,7 @@ class PHPExcel $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs ); } - return $this->addSheet($pSheet); + return $this->addSheet($pSheet, $iSheetIndex); } /** @@ -700,7 +710,8 @@ class PHPExcel } /** - * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells in the workbook + * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells + * and columns in the workbook */ public function garbageCollect() { @@ -711,12 +722,27 @@ class PHPExcel } foreach ($this->getWorksheetIterator() as $sheet) { + + // from cells foreach ($sheet->getCellCollection(false) as $cell) { ++$countReferencesCellXf[$cell->getXfIndex()]; } + + // from row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + ++$countReferencesCellXf[$rowDimension->getXfIndex()]; + } + } + + // from column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + ++$countReferencesCellXf[$columnDimension->getXfIndex()]; + } } - // remove those cellXfs that have zero references and create mapping so we can update xfIndex for all cells + // remove cellXfs without references and create mapping so we can update xfIndex + // for all cells and columns $countNeededCellXfs = 0; foreach ($this->_cellXfCollection as $index => $cellXf) { if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf @@ -728,16 +754,35 @@ class PHPExcel } $this->_cellXfCollection = array_values($this->_cellXfCollection); - // if we removed the first style by accident, recreate it + // update the index for all cellXfs + foreach ($this->_cellXfCollection as $i => $cellXf) { + echo $cellXf->setIndex($i); + } + + // make sure there is always at least one cellXf (there should be) if (count($this->_cellXfCollection) == 0) { $this->_cellXfCollection[] = new PHPExcel_Style(); } - // update the xfIndex for all cells + // update the xfIndex for all cells, row dimensions, column dimensions foreach ($this->getWorksheetIterator() as $sheet) { + + // for all cells foreach ($sheet->getCellCollection(false) as $cell) { $cell->setXfIndex( $map[$cell->getXfIndex()] ); } + + // for all row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] ); + } + } + + // for all column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); + } } // also do garbage collection for all the sheets diff --git a/libraries/PHPExcel/PHPExcel/Calculation.php b/libraries/PHPExcel/PHPExcel/Calculation.php index 5ade6558c..793734f91 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation.php +++ b/libraries/PHPExcel/PHPExcel/Calculation.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation { @@ -62,20 +62,21 @@ class PHPExcel_Calculation { // Opening bracket const CALCULATION_REGEXP_OPENBRACE = '\('; // Function - const CALCULATION_REGEXP_FUNCTION = '([A-Z][A-Z0-9\.]*)[\s]*\('; + const CALCULATION_REGEXP_FUNCTION = '@?([A-Z][A-Z0-9\.]*)[\s]*\('; // Cell reference (cell or range of cells, with or without a sheet reference) - const CALCULATION_REGEXP_CELLREF = '(((\w*)|(\'.*\')|(\".*\"))!)?\$?([a-z]+)\$?(\d+)(:\$?([a-z]+)\$?(\d+))?'; + const CALCULATION_REGEXP_CELLREF = '(((\w*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]+)\$?(\d+)'; // Named Range of cells const CALCULATION_REGEXP_NAMEDRANGE = '(((\w*)|(\'.*\')|(\".*\"))!)?([_A-Z][_A-Z0-9]*)'; // Error - const CALCULATION_REGEXP_ERROR = '\#[^!]+!'; + const CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?'; /** constants */ + const RETURN_ARRAY_AS_ERROR = 'error'; const RETURN_ARRAY_AS_VALUE = 'value'; const RETURN_ARRAY_AS_ARRAY = 'array'; - private static $returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; + private static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE; /** * Instance of this class @@ -110,7 +111,7 @@ class PHPExcel_Calculation { * @access private * @var float */ - private $_calculationCacheExpirationTime = 0.01; + private $_calculationCacheExpirationTime = 2.5; /** @@ -119,7 +120,7 @@ class PHPExcel_Calculation { * @access private * @var array */ - private $_operators = array('+', '-', '*', '/', '^', '&', '%', '_', '>', '<', '=', '>=', '<=', '<>'); + private $_operators = array('+', '-', '*', '/', '^', '&', '%', '~', '>', '<', '=', '>=', '<=', '<>', '|', ':'); /** @@ -128,7 +129,7 @@ class PHPExcel_Calculation { * @access private * @var array */ - private $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>'); + private $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>', '|', ':'); public $suppressFormulaErrors = false; public $formulaError = null; @@ -170,11 +171,11 @@ class PHPExcel_Calculation { 'argumentCount' => '2-5' ), 'AMORDEGRC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::AMORDEGRC', 'argumentCount' => '6,7' ), 'AMORLINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::AMORLINC', 'argumentCount' => '6,7' ), 'AND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, @@ -311,10 +312,11 @@ class PHPExcel_Calculation { ), 'COLUMN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_Functions::COLUMN', - 'argumentCount' => '-1' + 'argumentCount' => '-1', + 'passByReference' => array(true) ), 'COLUMNS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COLUMNS', 'argumentCount' => '1' ), 'COMBIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -386,7 +388,7 @@ class PHPExcel_Calculation { 'argumentCount' => '3,4' ), 'COUPNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::COUPNUM', 'argumentCount' => '3,4' ), 'COUPPCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -443,7 +445,7 @@ class PHPExcel_Calculation { ), 'DATEDIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::DATEDIF', - 'argumentCount' => '3' + 'argumentCount' => '2,3' ), 'DATEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::DATEVALUE', @@ -658,7 +660,7 @@ class PHPExcel_Calculation { 'argumentCount' => '3-5' ), 'FVSCHEDULE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::FVSCHEDULE', 'argumentCount' => '2' ), 'GAMMADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -731,7 +733,7 @@ class PHPExcel_Calculation { ), 'IFERROR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, 'functionCall' => 'PHPExcel_Calculation_Functions::STATEMENT_IFERROR', - 'argumentCount' => '1' + 'argumentCount' => '2' ), 'IMABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, 'functionCall' => 'PHPExcel_Calculation_Functions::IMABS', @@ -806,8 +808,9 @@ class PHPExcel_Calculation { 'argumentCount' => '1-4' ), 'INDIRECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '1,2' + 'functionCall' => 'PHPExcel_Calculation_Functions::INDIRECT', + 'argumentCount' => '1,2', + 'passCellReference'=> true ), 'INFO' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', @@ -830,7 +833,7 @@ class PHPExcel_Calculation { 'argumentCount' => '4-6' ), 'IRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::IRR', 'argumentCount' => '1,2' ), 'ISBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -870,7 +873,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'ISPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::ISPMT', 'argumentCount' => '4' ), 'ISREF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -961,6 +964,10 @@ class PHPExcel_Calculation { 'functionCall' => 'PHPExcel_Calculation_Functions::MAXA', 'argumentCount' => '1+' ), + 'MAXIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), 'MDETERM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, 'functionCall' => 'PHPExcel_Calculation_Functions::MDETERM', 'argumentCount' => '1' @@ -973,6 +980,10 @@ class PHPExcel_Calculation { 'functionCall' => 'PHPExcel_Calculation_Functions::MEDIAN', 'argumentCount' => '1+' ), + 'MEDIANIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), 'MID' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, 'functionCall' => 'PHPExcel_Calculation_Functions::MID', 'argumentCount' => '3' @@ -989,6 +1000,10 @@ class PHPExcel_Calculation { 'functionCall' => 'PHPExcel_Calculation_Functions::MINA', 'argumentCount' => '1+' ), + 'MINIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), 'MINUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, 'functionCall' => 'PHPExcel_Calculation_Functions::MINUTEOFHOUR', 'argumentCount' => '1' @@ -998,7 +1013,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'MIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::MIRR', 'argumentCount' => '3' ), 'MMULT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1111,7 +1126,9 @@ class PHPExcel_Calculation { ), 'OFFSET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_Functions::OFFSET', - 'argumentCount' => '3,5' + 'argumentCount' => '3,5', + 'passCellReference'=> true, + 'passByReference' => array(true) ), 'OR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, 'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_OR', @@ -1210,7 +1227,7 @@ class PHPExcel_Calculation { 'argumentCount' => '2,3' ), 'RATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::RATE', 'argumentCount' => '3-6' ), 'RECEIVED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1255,10 +1272,11 @@ class PHPExcel_Calculation { ), 'ROW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_Functions::ROW', - 'argumentCount' => '-1' + 'argumentCount' => '-1', + 'passByReference' => array(true) ), 'ROWS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::ROWS', 'argumentCount' => '1' ), 'RSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -1346,7 +1364,7 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'SUBSTITUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::SUBSTITUTE', 'argumentCount' => '3,4' ), 'SUBTOTAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1366,7 +1384,7 @@ class PHPExcel_Calculation { 'argumentCount' => '?' ), 'SUMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::SUMPRODUCT', 'argumentCount' => '1+' ), 'SUMSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1526,11 +1544,11 @@ class PHPExcel_Calculation { 'argumentCount' => '2+' ), 'XIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::XIRR', 'argumentCount' => '2,3' ), 'XNPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Functions::XNPV', 'argumentCount' => '3' ), 'YEAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, @@ -1554,8 +1572,8 @@ class PHPExcel_Calculation { 'argumentCount' => '5,6' ), 'ZTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', - 'argumentCount' => '?' + 'functionCall' => 'PHPExcel_Calculation_Functions::ZTEST', + 'argumentCount' => '2-3' ) ); @@ -1563,7 +1581,7 @@ class PHPExcel_Calculation { // Internal functions used for special control purposes private $_controlFunctions = array( 'MKMATRIX' => array('argumentCount' => '*', - 'functionCall' => array('self','_mkMatrix') + 'functionCall' => 'self::_mkMatrix' ) ); @@ -1592,7 +1610,7 @@ class PHPExcel_Calculation { * @throws Exception */ public final function __clone() { - throw new Exception ( 'Cloning a Singleton is not allowed!' ); + throw new Exception ('Cloning a Singleton is not allowed!'); } // function __clone() @@ -1605,6 +1623,7 @@ class PHPExcel_Calculation { */ public static function setArrayReturnType($returnType) { if (($returnType == self::RETURN_ARRAY_AS_VALUE) || + ($returnType == self::RETURN_ARRAY_AS_ERROR) || ($returnType == self::RETURN_ARRAY_AS_ARRAY)) { self::$returnArrayAsType = $returnType; return True; @@ -1686,7 +1705,7 @@ class PHPExcel_Calculation { * * @param float $pValue */ - public function setCalculationCacheExpirationTime($pValue = 0.01) { + public function setCalculationCacheExpirationTime($pValue = 2.5) { $this->_calculationCacheExpirationTime = $pValue; } // function setCalculationCacheExpirationTime() @@ -1765,19 +1784,49 @@ class PHPExcel_Calculation { if ($resetLog) { // Initialise the logging settings if requested $this->formulaError = null; - $this->debugLog = array(); - $this->debugLogStack = array(); + $this->debugLog = $this->debugLogStack = array(); + + $returnArrayAsType = self::$returnArrayAsType; + self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; } // Read the formula from the cell if (is_null($pCell)) { return null; } - $formula = $pCell->getValue(); - $cellID = $pCell->getCoordinate(); + if ($resetLog) { + self::$returnArrayAsType = $returnArrayAsType; + } // Execute the calculation for the cell formula - return self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); + $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell)); + + if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { + $testResult = PHPExcel_Calculation_Functions::flattenArray($result); + if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) { + return PHPExcel_Calculation_Functions::VALUE(); + } + // If there's only a single cell in the array, then we allow it + if (count($testResult) != 1) { + // If keys are numeric, then it's a matrix result rather than a cell range result, so we permit it + $r = array_shift(array_keys($result)); + if (!is_numeric($r)) { return PHPExcel_Calculation_Functions::VALUE(); } + if (is_array($result[$r])) { + $c = array_shift(array_keys($result[$r])); + if (!is_numeric($c)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + } + $result = array_shift($testResult); + } + + if (is_null($result)) { + return 0; + } elseif((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) { + return PHPExcel_Calculation_Functions::NaN(); + } + return $result; } // function calculateCellValue( @@ -1812,8 +1861,7 @@ class PHPExcel_Calculation { public function calculateFormula($formula, $cellID=null, PHPExcel_Cell $pCell = null) { // Initialise the logging settings $this->formulaError = null; - $this->debugLog = array(); - $this->debugLogStack = array(); + $this->debugLog = $this->debugLogStack = array(); // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache @@ -1849,30 +1897,34 @@ class PHPExcel_Calculation { $formulaLength = strlen($formula); if ($formulaLength < 1) return self::_wrapResult($formula); + $wsTitle = 'Wrk'; + if (!is_null($pCell)) { + $wsTitle = urlencode($pCell->getParent()->getTitle()); + } // Is calculation cacheing enabled? if (!is_null($cellID)) { if ($this->_calculationCacheEnabled) { // Is the value present in calculation cache? // echo 'Testing cache value
'; - if (isset($this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()])) { + if (isset($this->_calculationCache[$wsTitle][$cellID])) { // echo 'Value is in cache
'; - $this->_writeDebug($cellID,'Testing cache value'); + $this->_writeDebug('Testing cache value for cell '.$cellID); // Is cache still valid? - if ((time() + microtime()) - $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['time'] < $this->_calculationCacheExpirationTime) { + if ((time() + microtime(true)) - $this->_calculationCache[$wsTitle][$cellID]['time'] < $this->_calculationCacheExpirationTime) { // echo 'Cache time is still valid
'; - $this->_writeDebug($cellID,'Retrieving value from cache'); + $this->_writeDebug('Retrieving value for '.$cellID.' from cache'); // Return the cached result - $returnValue = $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['data']; -// echo 'Retrieving data value of '.$returnValue.' for '.$pCell->getCoordinate().' from cache
'; + $returnValue = $this->_calculationCache[$wsTitle][$cellID]['data']; +// echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache
'; if (is_array($returnValue)) { return array_shift(PHPExcel_Calculation_Functions::flattenArray($returnValue)); } return $returnValue; } else { // echo 'Cache has expired
'; - $this->_writeDebug($cellID,'Cache value has expired'); + $this->_writeDebug('Cache value for '.$cellID.' has expired'); // Clear the cache if it's no longer valid - unset($this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]); + unset($this->_calculationCache[$wsTitle][$cellID]); } } } @@ -1886,16 +1938,12 @@ class PHPExcel_Calculation { // Save to calculation cache if (!is_null($cellID)) { if ($this->_calculationCacheEnabled) { - $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['time'] = (time() + microtime()); - $this->_calculationCache[$pCell->getParent()->getTitle()][$pCell->getCoordinate()]['data'] = $cellValue; + $this->_calculationCache[$wsTitle][$cellID]['time'] = (time() + microtime(true)); + $this->_calculationCache[$wsTitle][$cellID]['data'] = $cellValue; } } // Return the calculated value - if (is_array($cellValue)) { - $cellValue = array_shift(PHPExcel_Calculation_Functions::flattenArray($cellValue)); - } - return $cellValue; } // function _calculateFormulaValue() @@ -1903,8 +1951,14 @@ class PHPExcel_Calculation { /** * Ensure that paired matrix operands are both matrices and of the same size * - * @param mixed $operand1 First matrix operand - * @param mixed $operand2 Second matrix operand + * @param mixed &$operand1 First matrix operand + * @param mixed &$operand2 Second matrix operand + * @param integer $resize Flag indicating whether the matrices should be resized to match + * and (if so), whether the smaller dimension should grow or the + * larger should shrink. + * 0 = no resize + * 1 = shrink to fit + * 2 = extend to fit */ private static function _checkMatrixOperands(&$operand1,&$operand2,$resize = 1) { // Examine each of the two operands, and turn them into an array if they aren't one already @@ -1919,36 +1973,29 @@ class PHPExcel_Calculation { $resize = 0; } - // Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger + list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($operand1); + list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($operand2); + if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) { + $resize = 1; + } + if ($resize == 2) { + // Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger self::_resizeMatricesExtend($operand1,$operand2); } elseif ($resize == 1) { + // Given two matrices of (potentially) unequal size, convert the larger in each dimension to match the smaller self::_resizeMatricesShrink($operand1,$operand2); } } // function _checkMatrixOperands() - /** - * Re-index a matrix with straight numeric keys starting from row 0, column 0 - * - * @param mixed $matrix matrix operand - * @return array The re-indexed matrix - */ - private static function _reindexMatrixDimensions($matrix) { - foreach($matrix as $rowKey => $rowValue) { - $matrix[$rowKey] = array_values($rowValue); - } - return array_values($matrix); - } // function _getMatrixDimensions() - - /** * Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0 * - * @param mixed $matrix matrix operand + * @param mixed &$matrix matrix operand * @return array An array comprising the number of rows, and number of columns */ - private static function _getMatrixDimensions(&$matrix) { + public static function _getMatrixDimensions(&$matrix) { $matrixRows = count($matrix); $matrixColumns = 0; foreach($matrix as $rowKey => $rowValue) { @@ -1966,8 +2013,8 @@ class PHPExcel_Calculation { /** * Ensure that paired matrix operands are both matrices of the same size * - * @param mixed $matrix1 First matrix operand - * @param mixed $matrix2 Second matrix operand + * @param mixed &$matrix1 First matrix operand + * @param mixed &$matrix2 Second matrix operand */ private static function _resizeMatricesShrink(&$matrix1,&$matrix2) { list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($matrix1); @@ -2008,8 +2055,8 @@ class PHPExcel_Calculation { /** * Ensure that paired matrix operands are both matrices of the same size * - * @param mixed $matrix1 First matrix operand - * @param mixed $matrix2 Second matrix operand + * @param mixed &$matrix1 First matrix operand + * @param mixed &$matrix2 Second matrix operand */ private static function _resizeMatricesExtend(&$matrix1,&$matrix2) { list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($matrix1); @@ -2059,24 +2106,17 @@ class PHPExcel_Calculation { */ private static function _showValue($value) { if (is_array($value)) { - $retVal = ''; - $i = 0; + $returnMatrix = array(); + $pad = $rpad = ', '; foreach($value as $row) { if (is_array($row)) { - if ($i > 0) { $retVal .= '; '; } - $j = 0; - foreach($row as $column) { - if ($j > 0) { $retVal .= ', '; } - $retVal .= $column; - ++$j; - } + $returnMatrix[] = implode($pad,$row); + $rpad = '; '; } else { - if ($i > 0) { $retVal .= ', '; } - $retVal .= $row; + $returnMatrix[] = $row; } - ++$i; } - return '{ '.$retVal.' }'; + return '{ '.implode($rpad,$returnMatrix).' }'; } elseif(is_bool($value)) { return ($value) ? 'TRUE' : 'FALSE'; } @@ -2128,17 +2168,16 @@ class PHPExcel_Calculation { // Convert any Excel matrix references to the MKMATRIX() function if (strpos($formula,'{') !== false) { - // Open and Closed counts used for trapping mismatched braces in the formula - $openCount = $closeCount = 0; // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators if (strpos($formula,'"') !== false) { // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded // the formula $temp = explode('"',$formula); - $i = 0; - foreach($temp as &$value) { + // Open and Closed counts used for trapping mismatched braces in the formula + $openCount = $closeCount = 0; + foreach($temp as $i => &$value) { // Only count/replace in alternate array entries - if (($i++ % 2) == 0) { + if (($i % 2) == 0) { $openCount += substr_count($value,'{'); $closeCount += substr_count($value,'}'); $value = str_replace($matrixReplaceFrom,$matrixReplaceTo,$value); @@ -2149,8 +2188,8 @@ class PHPExcel_Calculation { $formula = implode('"',$temp); } else { // If there's no quoted strings, then we do a simple count/replace - $openCount += substr_count($formula,'{'); - $closeCount += substr_count($formula,'}'); + $openCount = substr_count($formula,'{'); + $closeCount = substr_count($formula,'}'); $formula = str_replace($matrixReplaceFrom,$matrixReplaceTo,$formula); } // Trap for mismatched braces and trigger an appropriate error @@ -2190,7 +2229,8 @@ class PHPExcel_Calculation { $operatorAssociativity = array('^' => 0, // Exponentiation '*' => 0, '/' => 0, // Multiplication and Division '+' => 0, '-' => 0, // Addition and Subtraction - '&' => 1, // Concatenation + '&' => 0, // Concatenation + '|' => 0, ':' => 0, // Intersect and Range '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison ); // Comparison (Boolean) Operators @@ -2200,7 +2240,9 @@ class PHPExcel_Calculation { // Operator Precedence // This list includes all valid operators, whether binary (including boolean) or unary (such as %) // Array key is the operator, the value is its precedence - $operatorPrecedence = array('_' => 6, // Negation + $operatorPrecedence = array(':' => 8, // Range + '|' => 7, // Intersect + '~' => 6, // Negation '%' => 5, // Percentage '^' => 4, // Exponentiation '*' => 3, '/' => 3, // Multiplication and Division @@ -2215,7 +2257,8 @@ class PHPExcel_Calculation { '|'.self::CALCULATION_REGEXP_OPENBRACE. '|'.self::CALCULATION_REGEXP_CELLREF. '|'.self::CALCULATION_REGEXP_NAMEDRANGE. - ')/i'; + '|'.self::CALCULATION_REGEXP_ERROR. + ')/si'; // Start with initialisation $index = 0; @@ -2242,44 +2285,43 @@ class PHPExcel_Calculation { if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus? // echo 'Element is a Negation operator
'; - $stack->push('_'); // Put a negation on the stack + $stack->push('Unary Operator','~'); // Put a negation on the stack ++$index; // and drop the negation symbol } elseif ($opCharacter == '%' && $expectingOperator) { // echo 'Element is a Percentage operator
'; - $stack->push('%'); // Put a percentage on the stack + $stack->push('Unary Operator','%'); // Put a percentage on the stack ++$index; } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (rather than plus) can be discarded? // echo 'Element is a Positive number, not Plus operator
'; ++$index; // Drop the redundant plus symbol - } elseif (($opCharacter == '_') && (!$isOperandOrFunction)) { // We have to explicitly deny an underscore, because it's legal on - return $this->_raiseFormulaError("Formula Error: Illegal character '_'"); // the stack but not in the input expression - // Note that _ is a valid first character in named ranges - // and this will need modifying soon when we start integrating - // with PHPExcel proper + } elseif (($opCharacter == '~') && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde, because it's legal + return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression } elseif ((in_array($opCharacter, $this->_operators) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? // echo 'Element with value '.$opCharacter.' is an Operator
'; while($stack->count() > 0 && ($o2 = $stack->last()) && - in_array($o2, $this->_operators) && - ($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2])) { + in_array($o2['value'], $this->_operators) && + @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } - $stack->push($opCharacter); // Finally put our current operator onto the stack + $stack->push('Binary Operator',$opCharacter); // Finally put our current operator onto the stack ++$index; $expectingOperator = false; } elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis? // echo 'Element is a Closing bracket
'; $expectingOperand = false; - while (($o2 = $stack->pop()) != '(') { // Pop off the stack back to the last ( + while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( if (is_null($o2)) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"'); else $output[] = $o2; } - if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $stack->last(2), $matches)) { // Did this parenthesis just close a function? + $d = $stack->last(2); + if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) { // Did this parenthesis just close a function? $functionName = $matches[1]; // Get the function name // echo 'Closed Function is '.$functionName.'
'; - $argumentCount = $stack->pop(); // See how many arguments there were (argument count is the next value stored on the stack) + $d = $stack->pop(); + $argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack) // if ($argumentCount == 0) { // echo 'With no arguments
'; // } elseif ($argumentCount == 1) { @@ -2287,7 +2329,7 @@ class PHPExcel_Calculation { // } else { // echo 'With '.$argumentCount.' arguments
'; // } - $output[] = $argumentCount; // Dump the argument count on the output + $output[] = $d; // Dump the argument count on the output $output[] = $stack->pop(); // Pop the function and push onto the output if (array_key_exists($functionName, $this->_controlFunctions)) { // echo 'Built-in function '.$functionName.'
'; @@ -2349,27 +2391,29 @@ class PHPExcel_Calculation { } elseif ($opCharacter == ',') { // Is this the comma separator for function arguments? // echo 'Element is a Function argument separator
'; - while (($o2 = $stack->pop()) != '(') { + while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( if (is_null($o2)) return $this->_raiseFormulaError("Formula Error: Unexpected ','"); else $output[] = $o2; // pop the argument expression stuff and push onto the output } // If we've a comma when we're expecting an operand, then what we actually have is a null operand; // so push a null onto the stack if (($expectingOperand) || (!$expectingOperator)) { - $output[] = $this->_ExcelConstants['NULL']; + $output[] = array('type' => 'NULL Value', 'value' => $this->_ExcelConstants['NULL'], 'reference' => NULL); } // make sure there was a function - if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $stack->last(2), $matches)) + $d = $stack->last(2); + if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) return $this->_raiseFormulaError("Formula Error: Unexpected ','"); - $stack->push($stack->pop()+1); // increment the argument count - $stack->push('('); // put the ( back on, we'll need to pop back to it again + $d = $stack->pop(); + $stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count + $stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again $expectingOperator = false; $expectingOperand = true; ++$index; } elseif ($opCharacter == '(' && !$expectingOperator) { // echo 'Element is an Opening Bracket
'; - $stack->push('('); + $stack->push('Brace', '('); ++$index; } elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number? @@ -2382,28 +2426,27 @@ class PHPExcel_Calculation { if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $val, $matches)) { $val = preg_replace('/\s/','',$val); // echo 'Element '.$val.' is a Function
'; - if (array_key_exists(strtoupper($matches[1]), $this->_controlFunctions) || array_key_exists(strtoupper($matches[1]), $this->_PHPExcelFunctions)) { // it's a func - $stack->push(strtoupper($val)); + if (array_key_exists(strtoupper($matches[1]), $this->_PHPExcelFunctions) || array_key_exists(strtoupper($matches[1]), $this->_controlFunctions)) { // it's a func + $stack->push('Function', strtoupper($val)); $ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch); if ($ax) { - $stack->push(0); + $stack->push('Operand Count for Function '.strtoupper($val).')', 0); $expectingOperator = true; } else { - $stack->push(1); + $stack->push('Operand Count for Function '.strtoupper($val).')', 1); $expectingOperator = false; } - $stack->push('('); + $stack->push('Brace', '('); } else { // it's a var w/ implicit multiplication - $val = $matches[1]; - $output[] = $val; + $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => NULL); } } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) { // echo 'Element '.$val.' is a Cell reference
'; // Watch for this case-change when modifying to allow cell references in different worksheets... // Should only be applied to the actual cell column, not the worksheet name -// $cellRef = strtoupper($val); + $cellRef = strtoupper($val); // $output[] = $cellRef; - $output[] = $val; + $output[] = array('type' => 'Cell Reference', 'value' => $val, 'reference' => $cellRef); // $expectingOperator = false; } else { // it's a variable, constant, string, number or boolean // echo 'Element is a Variable, Constant, String, Number or Boolean
'; @@ -2412,25 +2455,25 @@ class PHPExcel_Calculation { $val = str_replace('""','"',$val); } elseif (is_numeric($val)) { // echo 'Element is a Number
'; - if ((strpos($val,'.') !== False) || (stripos($val,'e') !== False)) { + if ((strpos($val,'.') !== False) || (stripos($val,'e') !== False) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) { // echo 'Casting '.$val.' to float
'; $val = (float) $val; } else { // echo 'Casting '.$val.' to integer
'; $val = (integer) $val; } -// } elseif (array_key_exists(trim(strtoupper($val)), $this->_ExcelConstants)) { -// $excelConstant = trim(strtoupper($val)); -// echo 'Element '.$val.' is an Excel Constant
'; -// $val = $this->_ExcelConstants[$excelConstant]; + } elseif (array_key_exists(trim(strtoupper($val)), $this->_ExcelConstants)) { + $excelConstant = trim(strtoupper($val)); +// echo 'Element '.$excelConstant.' is an Excel Constant
'; + $val = $this->_ExcelConstants[$excelConstant]; } - $output[] = $val; + $output[] = array('type' => 'Value', 'value' => $val, 'reference' => NULL); } $index += $length; } elseif ($opCharacter == ')') { // miscellaneous error checking if ($expectingOperand) { - $output[] = $this->_ExcelConstants['NULL']; + $output[] = array('type' => 'Null Value', 'value' => $this->_ExcelConstants['NULL'], 'reference' => NULL); $expectingOperand = false; $expectingOperator = True; } else { @@ -2452,14 +2495,34 @@ class PHPExcel_Calculation { } } // Ignore white space - while (substr($formula, $index, 1) == ' ') { + while (($formula{$index} == "\n") || ($formula{$index} == "\r")) { ++$index; } + if ($formula{$index} == ' ') { + while ($formula{$index} == ' ') { + ++$index; + } + // If we're expecting an operator, but only have a space between the previous and next operands (and both are + // Cell References) then we have an INTERSECTION operator +// echo 'Possible Intersect Operator
'; + if (($expectingOperator) && (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'.*/i', substr($formula, $index), $match)) && + ($output[count($output)-1]['type'] == 'Cell Reference')) { +// echo 'Element is an Intersect Operator
'; + while($stack->count() > 0 && + ($o2 = $stack->last()) && + in_array($o2['value'], $this->_operators) && + @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { + $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output + } + $stack->push('Binary Operator','|'); // Put an Intersect Operator on the stack + $expectingOperator = false; + } + } } - while (!is_null($opCharacter = $stack->pop())) { // pop everything off the stack and push onto output - if ($opCharacter == '(') return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced - $output[] = $opCharacter; + while (!is_null($op = $stack->pop())) { // pop everything off the stack and push onto output + if ($opCharacter['value'] == '(') return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced + $output[] = $op; } return $output; } // function _parseFormula() @@ -2472,16 +2535,25 @@ class PHPExcel_Calculation { $stack = new PHPExcel_Token_Stack; // Loop through each token in turn - foreach ($tokens as $token) { + foreach ($tokens as $tokenData) { +// print_r($tokenData); +// echo '
'; + $token = $tokenData['value']; // echo 'Token is '.$token.'
'; // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack if (in_array($token, $this->_binaryOperators, true)) { // echo 'Token is a binary operator
'; // We must have two operands, error if we don't - if (is_null($operand2 = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); - if (is_null($operand1 = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); + if (is_null($operand2Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); + if (is_null($operand1Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); // Log what we're doing - $this->_writeDebug($cellID,'Evaluating '.self::_showValue($operand1).' '.$token.' '.self::_showValue($operand2)); + $operand1 = $operand1Data['value']; + $operand2 = $operand2Data['value']; + if ($token == ':') { + $this->_writeDebug('Evaluating Range '.self::_showValue($operand1Data['reference']).$token.self::_showValue($operand2Data['reference'])); + } else { + $this->_writeDebug('Evaluating '.self::_showValue($operand1).' '.$token.' '.self::_showValue($operand2)); + } // Process the operation in the appropriate manner switch ($token) { // Comparison (Boolean) Operators @@ -2494,6 +2566,53 @@ class PHPExcel_Calculation { $this->_executeBinaryComparisonOperation($cellID,$operand1,$operand2,$token,$stack); break; // Binary Operators + case ':' : // Range + $sheet1 = $sheet2 = ''; + if (strpos($operand1Data['reference'],'!') !== false) { + list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']); + } else { + $sheet1 = $pCell->getParent()->getTitle(); + } + if (strpos($operand2Data['reference'],'!') !== false) { + list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']); + } else { + $sheet2 = $sheet1; + } + if ($sheet1 == $sheet2) { + if (is_null($operand1Data['reference'])) { + if ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) { + $operand1Data['reference'] = $pCell->getColumn().$operand1Data['value']; + } elseif (trim($operand1Data['reference']) == '') { + $operand1Data['reference'] = $pCell->getColumn().$pCell->getRow(); + } else { + $operand1Data['reference'] = $operand1Data['value'].$pCell->getRow(); + } + } + if (is_null($operand2Data['reference'])) { + if ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) { + $operand2Data['reference'] = $pCell->getColumn().$operand2Data['value']; + } elseif (trim($operand2Data['reference']) == '') { + $operand2Data['reference'] = $pCell->getColumn().$pCell->getRow(); + } else { + $operand2Data['reference'] = $operand2Data['value'].$pCell->getRow(); + } + } + + $oData = array_merge(explode(':',$operand1Data['reference']),explode(':',$operand2Data['reference'])); + $oCol = $oRow = array(); + foreach($oData as $oDatum) { + $oCR = PHPExcel_Cell::coordinateFromString($oDatum); + $oCol[] = PHPExcel_Cell::columnIndexFromString($oCR[0]) - 1; + $oRow[] = $oCR[1]; + } + $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); + $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($sheet1), false); + $stack->push('Cell Reference',$cellValue,$cellRef); + } else { + $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL); + } + + break; case '+' : // Addition $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'plusEquals',$stack); break; @@ -2513,9 +2632,15 @@ class PHPExcel_Calculation { // If either of the operands is a matrix, we need to treat them both as matrices // (converting the other operand to a matrix if need be); then perform the required // matrix operation + if (is_bool($operand1)) { + $operand1 = ($operand1) ? 'TRUE' : 'FALSE'; + } + if (is_bool($operand2)) { + $operand2 = ($operand2) ? 'TRUE' : 'FALSE'; + } if ((is_array($operand1)) || (is_array($operand2))) { // Ensure that both operands are arrays/matrices - self::_checkMatrixOperands($operand1,$operand2); + self::_checkMatrixOperands($operand1,$operand2,2); try { // Convert operand 1 from a PHP array to a matrix $matrix = new Matrix($operand1); @@ -2523,48 +2648,63 @@ class PHPExcel_Calculation { $matrixResult = $matrix->concat($operand2); $result = $matrixResult->getArray(); } catch (Exception $ex) { - $this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage()); + $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); $result = '#VALUE!'; } } else { $result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"'; } - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); - $stack->push($result); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); + $stack->push('Value',$result); + break; + case '|' : // Intersect + $rowIntersect = array_intersect_key($operand1,$operand2); + $cellIntersect = $oCol = $oRow = array(); + foreach(array_keys($rowIntersect) as $col) { + $oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1; + $cellIntersect[$col] = array_intersect_key($operand1[$col],$operand2[$col]); + foreach($cellIntersect[$col] as $row => $data) { + $oRow[] = $row; + } + } + $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($cellIntersect)); + $stack->push('Value',$cellIntersect,$cellRef); break; } // if the token is a unary operator, pop one value off the stack, do the operation, and push it back on - } elseif (($token === "_") || ($token === "%")) { + } elseif (($token === '~') || ($token === '%')) { // echo 'Token is a unary operator
'; if (is_null($arg = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); - if ($token === "_") { + $arg = $arg['value']; + if ($token === '~') { // echo 'Token is a negation operator
'; - $this->_writeDebug($cellID,'Evaluating Negation of '.self::_showValue($arg)); + $this->_writeDebug('Evaluating Negation of '.self::_showValue($arg)); $multiplier = -1; } else { // echo 'Token is a percentile operator
'; - $this->_writeDebug($cellID,'Evaluating Percentile of '.self::_showValue($arg)); + $this->_writeDebug('Evaluating Percentile of '.self::_showValue($arg)); $multiplier = 0.01; } if (is_array($arg)) { - self::_checkMatrixOperands($arg,$multiplier); + self::_checkMatrixOperands($arg,$multiplier,2); try { $matrix1 = new Matrix($arg); $matrixResult = $matrix1->arrayTimesEquals($multiplier); $result = $matrixResult->getArray(); } catch (Exception $ex) { - $this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage()); + $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); $result = '#VALUE!'; } - + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); + $stack->push('Value',$result); } else { - $result = $multiplier * $arg; + $this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack); } - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); - $stack->push($result); } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) { + $cellRef = null; // echo 'Element '.$token.' is a Cell reference
'; if (isset($matches[8])) { // echo 'Reference is a Range of cells
'; @@ -2574,15 +2714,16 @@ class PHPExcel_Calculation { } else { $cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10]; if ($matches[2] > '') { + $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_writeDebug($cellID,'Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]); + $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]); $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false); - $this->_writeDebug($cellID,'Evaluation Result for cells '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cells '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; - $this->_writeDebug($cellID,'Evaluating Cell Range '.$cellRef.' in current worksheet'); + $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in current worksheet'); $cellValue = $this->extractCellRange($cellRef, $pCell->getParent(), false); - $this->_writeDebug($cellID,'Evaluation Result for cells '.$cellRef.' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cells '.$cellRef.' is '.self::_showTypeDetails($cellValue)); } } } else { @@ -2593,94 +2734,123 @@ class PHPExcel_Calculation { } else { $cellRef = $matches[6].$matches[7]; if ($matches[2] > '') { + $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_writeDebug($cellID,'Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]); - if ($pCell->getParent()->cellExists($cellRef)) { + $this->_writeDebug('Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]); + if ($pCell->getParent()->getParent()->getSheetByName($matches[2])->cellExists($cellRef)) { $cellValue = $this->extractCellRange($cellRef, $pCell->getParent()->getParent()->getSheetByName($matches[2]), false); } else { - $cellValue = null; + $cellValue = PHPExcel_Calculation_Functions::REF(); } - $this->_writeDebug($cellID,'Evaluation Result for cell '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cell '.$cellRef.' in worksheet '.$matches[2].' is '.self::_showTypeDetails($cellValue)); } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; - $this->_writeDebug($cellID,'Evaluating Cell '.$cellRef.' in current worksheet'); + $this->_writeDebug('Evaluating Cell '.$cellRef.' in current worksheet'); if ($pCell->getParent()->cellExists($cellRef)) { - $cellValue = $pCell->getParent()->getCell($cellRef)->getCalculatedValue(false); + $cellValue = $this->extractCellRange($cellRef, $pCell->getParent(), false); } else { - $cellValue = ''; + $cellValue = NULL; } - $this->_writeDebug($cellID,'Evaluation Result for cell '.$cellRef.' is '.self::_showTypeDetails($cellValue)); + $this->_writeDebug('Evaluation Result for cell '.$cellRef.' is '.self::_showTypeDetails($cellValue)); } } } - $stack->push($cellValue); + $stack->push('Value',$cellValue,$cellRef); // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on } elseif (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $token, $matches)) { // echo 'Token is a function
'; $functionName = $matches[1]; $argCount = $stack->pop(); + $argCount = $argCount['value']; if ($functionName != 'MKMATRIX') { - $this->_writeDebug($cellID,'Evaluating Function '.$functionName.'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's')); + $this->_writeDebug('Evaluating Function '.$functionName.'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's')); } - if ((array_key_exists($functionName, $this->_controlFunctions)) || (array_key_exists($functionName, $this->_PHPExcelFunctions))) { // function - if (array_key_exists($functionName, $this->_controlFunctions)) { - $functionCall = $this->_controlFunctions[$functionName]['functionCall']; - } elseif (array_key_exists($functionName, $this->_PHPExcelFunctions)) { + if ((array_key_exists($functionName, $this->_PHPExcelFunctions)) || (array_key_exists($functionName, $this->_controlFunctions))) { // function + if (array_key_exists($functionName, $this->_PHPExcelFunctions)) { $functionCall = $this->_PHPExcelFunctions[$functionName]['functionCall']; + $passByReference = isset($this->_PHPExcelFunctions[$functionName]['passByReference']); + $passCellReference = isset($this->_PHPExcelFunctions[$functionName]['passCellReference']); + } elseif (array_key_exists($functionName, $this->_controlFunctions)) { + $functionCall = $this->_controlFunctions[$functionName]['functionCall']; + $passByReference = isset($this->_controlFunctions[$functionName]['passByReference']); + $passCellReference = isset($this->_controlFunctions[$functionName]['passCellReference']); } // get the arguments for this function // echo 'Function '.$functionName.' expects '.$argCount.' arguments
'; - $args = array(); - for ($i = $argCount; $i > 0; --$i) { + $args = $argArrayVals = array(); + for ($i = 0; $i < $argCount; ++$i) { $arg = $stack->pop(); -// if (is_null($arg)) return $this->_raiseFormulaError("internal error"); - $args[$i] = $arg; + $a = $argCount - $i - 1; + if (($passByReference) && + (isset($this->_PHPExcelFunctions[$functionName]['passByReference'][$a])) && + ($this->_PHPExcelFunctions[$functionName]['passByReference'][$a])) { + if (is_null($arg['reference'])) { + $args[] = $cellID; + if ($functionName != 'MKMATRIX') { $argArrayVals[] = self::_showValue($cellID); } + } else { + $args[] = $arg['reference']; + if ($functionName != 'MKMATRIX') { $argArrayVals[] = self::_showValue($arg['reference']); } + } + } else { + $args[] = self::_unwrapResult($arg['value']); + if ($functionName != 'MKMATRIX') { $argArrayVals[] = self::_showValue($arg['value']); } + } } // Reverse the order of the arguments - ksort($args); + krsort($args); + if (($passByReference) && ($argCount == 0)) { + $args[] = $cellID; + $argArrayVals[] = self::_showValue($cellID); + } // echo 'Arguments are: '; // print_r($args); // echo '
'; if ($functionName != 'MKMATRIX') { - $argArrayVals = array(); - foreach($args as &$arg) { - $argArrayVals[] = self::_showValue($arg); - $arg = self::_unwrapResult($arg); - } - unset($arg); - $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.implode(', ',$argArrayVals).' )'); + krsort($argArrayVals); + $this->_writeDebug('Evaluating '. $functionName.'( '.implode(', ',$argArrayVals).' )'); } // Process each argument in turn, building the return value as an array // if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) { // $operand1 = $args[1]; -// $this->_writeDebug($cellID,'Argument is a matrix: '.self::_showValue($operand1)); +// $this->_writeDebug('Argument is a matrix: '.self::_showValue($operand1)); // $result = array(); // $row = 0; // foreach($operand1 as $args) { // if (is_array($args)) { // foreach($args as $arg) { -// $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.self::_showValue($arg).' )'); +// $this->_writeDebug('Evaluating '. $functionName.'( '.self::_showValue($arg).' )'); // $r = call_user_func_array($functionCall,$arg); -// $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($r)); +// $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($r)); // $result[$row][] = $r; // } // ++$row; // } else { -// $this->_writeDebug($cellID,'Evaluating '. $functionName.'( '.self::_showValue($args).' )'); +// $this->_writeDebug('Evaluating '. $functionName.'( '.self::_showValue($args).' )'); // $r = call_user_func_array($functionCall,$args); -// $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($r)); +// $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($r)); // $result[] = $r; // } // } // } else { // Process the argument with the appropriate function call - $result = call_user_func_array($functionCall,$args); + if ($passCellReference) { + $args[] = $pCell; + } + if (strpos($functionCall,'::') !== false) { + $result = call_user_func_array(explode('::',$functionCall),$args); + } else { + foreach($args as &$arg) { + $arg = PHPExcel_Calculation_Functions::flattenSingleValue($arg); + } + unset($arg); + $result = call_user_func_array($functionCall,$args); + } // } if ($functionName != 'MKMATRIX') { - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); } - $stack->push(self::_wrapResult($result)); + $stack->push('Value',self::_wrapResult($result)); } } else { @@ -2688,20 +2858,20 @@ class PHPExcel_Calculation { if (array_key_exists(strtoupper($token), $this->_ExcelConstants)) { $excelConstant = strtoupper($token); // echo 'Token is a PHPExcel constant: '.$excelConstant.'
'; - $stack->push($this->_ExcelConstants[$excelConstant]); - $this->_writeDebug($cellID,'Evaluating Constant '.$excelConstant.' as '.self::_showTypeDetails($this->_ExcelConstants[$excelConstant])); - } elseif ((is_null($token)) || ($token == '') || (is_bool($token)) || (is_numeric($token)) || ($token{0} == '"') || ($token{0} == '#')) { -// echo 'Token is a number, boolean, string or an Excel error
'; - $stack->push($token); - // if the token is a constant, push the constant value on the stack + $stack->push('Constant Value',$this->_ExcelConstants[$excelConstant]); + $this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.self::_showTypeDetails($this->_ExcelConstants[$excelConstant])); + } elseif ((is_numeric($token)) || (is_bool($token)) || (is_null($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { +// echo 'Token is a number, boolean, string, null or an Excel error
'; + $stack->push('Value',$token); + // if the token is a named range, push the named range name onto the stack } elseif (preg_match('/^'.self::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $token, $matches)) { // echo 'Token is a named range
'; $namedRange = $matches[6]; // echo 'Named Range is '.$namedRange.'
'; - $this->_writeDebug($cellID,'Evaluating Named Range '.$namedRange); - $cellValue = $this->extractNamedRange($namedRange, $pCell->getParent(), false); - $this->_writeDebug($cellID,'Evaluation Result for named range '.$namedRange.' is '.self::_showTypeDetails($cellValue)); - $stack->push($cellValue); + $this->_writeDebug('Evaluating Named Range '.$namedRange); + $cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCell->getParent() : null), false); + $this->_writeDebug('Evaluation Result for named range '.$namedRange.' is '.self::_showTypeDetails($cellValue)); + $stack->push('Named Range',$cellValue,$namedRange); } else { return $this->_raiseFormulaError("undefined variable '$token'"); } @@ -2710,9 +2880,11 @@ class PHPExcel_Calculation { // when we're out of tokens, the stack should have a single element, the final result if ($stack->count() != 1) return $this->_raiseFormulaError("internal error"); $output = $stack->pop(); - if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { - return array_unshift(array_unshift($output)); - } + $output = $output['value']; + +// if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { +// return array_shift(PHPExcel_Calculation_Functions::flattenArray($output)); +// } return $output; } // function _processTokenStack() @@ -2722,18 +2894,18 @@ class PHPExcel_Calculation { if (is_string($operand)) { // We only need special validations for the operand if it is a string // Start by stripping off the quotation marks we use to identify true excel string values internally - if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand,'"'); } + if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand); } // If the string is a numeric value, we treat it as a numeric, so no further testing if (!is_numeric($operand)) { // If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations if ($operand > '' && $operand{0} == '#') { - $stack->push($operand); - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($operand)); + $stack->push('Value', $operand); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($operand)); return false; - } else { - // If not a numeric, then it's a text string, and so can't be used in mathematical binary operations - $stack->push('#VALUE!'); - $this->_writeDebug($cellID,'Evaluation Result is a '.self::_showTypeDetails('#VALUE!')); + } elseif (!PHPExcel_Shared_String::convertToNumberIfFraction($operand)) { + // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations + $stack->push('Value', '#VALUE!'); + $this->_writeDebug('Evaluation Result is a '.self::_showTypeDetails('#VALUE!')); return false; } } @@ -2744,10 +2916,45 @@ class PHPExcel_Calculation { } // function _validateBinaryOperand() - private function _executeBinaryComparisonOperation($cellID,$operand1,$operand2,$operation,&$stack) { - // Validate the two operands + private function _executeBinaryComparisonOperation($cellID,$operand1,$operand2,$operation,&$stack,$recursingArrays=false) { + // If we're dealing with matrix operations, we want a matrix result + if ((is_array($operand1)) || (is_array($operand2))) { + $result = array(); + if ((is_array($operand1)) && (!is_array($operand2))) { + foreach($operand1 as $x => $operandData) { + $this->_writeDebug('Evaluating '.self::_showValue($operandData).' '.$operation.' '.self::_showValue($operand2)); + $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2,$operation,$stack); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } elseif ((!is_array($operand1)) && (is_array($operand2))) { + foreach($operand2 as $x => $operandData) { + $this->_writeDebug('Evaluating '.self::_showValue($operand1).' '.$operation.' '.self::_showValue($operandData)); + $this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } else { + if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); } + foreach($operand1 as $x => $operandData) { + $this->_writeDebug('Evaluating '.self::_showValue($operandData).' '.$operation.' '.self::_showValue($operand2[$x])); + $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,True); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } + // Log the result details + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); + // And push the result onto the stack + $stack->push('Array',$result); + return true; + } - // If we're dealing with non-matrix operations, execute the necessary operation + // Simple validate the two operands if they are string values + if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { $operand1 = self::_unwrapResult($operand1); } + if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { $operand2 = self::_unwrapResult($operand2); } + + // execute the necessary operation switch ($operation) { // Greater than case '>': @@ -2776,12 +2983,13 @@ class PHPExcel_Calculation { } // Log the result details - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); // And push the result onto the stack - $stack->push($result); + $stack->push('Value',$result); return true; } // function _executeBinaryComparisonOperation() + private function _executeNumericBinaryOperation($cellID,$operand1,$operand2,$operation,$matrixFunction,&$stack) { // Validate the two operands if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return false; @@ -2792,7 +3000,7 @@ class PHPExcel_Calculation { // matrix operation if ((is_array($operand1)) || (is_array($operand2))) { // Ensure that both operands are arrays/matrices - self::_checkMatrixOperands($operand1,$operand2); + self::_checkMatrixOperands($operand1,$operand2,2); try { // Convert operand 1 from a PHP array to a matrix $matrix = new Matrix($operand1); @@ -2800,7 +3008,7 @@ class PHPExcel_Calculation { $matrixResult = $matrix->$matrixFunction($operand2); $result = $matrixResult->getArray(); } catch (Exception $ex) { - $this->_writeDebug($cellID,'JAMA Matrix Exception: '.$ex->getMessage()); + $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); $result = '#VALUE!'; } } else { @@ -2822,8 +3030,8 @@ class PHPExcel_Calculation { case '/': if ($operand2 == 0) { // Trap for Divide by Zero error - $stack->push('#DIV/0!'); - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails('#DIV/0!')); + $stack->push('Value','#DIV/0!'); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails('#DIV/0!')); return false; } else { $result = $operand1/$operand2; @@ -2837,19 +3045,17 @@ class PHPExcel_Calculation { } // Log the result details - $this->_writeDebug($cellID,'Evaluation Result is '.self::_showTypeDetails($result)); + $this->_writeDebug('Evaluation Result is '.self::_showTypeDetails($result)); // And push the result onto the stack - $stack->push($result); + $stack->push('Value',$result); return true; } // function _executeNumericBinaryOperation() - private function _writeDebug($cellID,$message) { + private function _writeDebug($message) { // Only write the debug log if logging is enabled if ($this->writeDebugLog) { -// $prefix = substr(implode(' -> ',$this->debugLogStack).' -> ',4+strlen($this->debugLogStack[0])); - $prefix = implode(' -> ',$this->debugLogStack).' -> '; - $this->debugLog[] = $prefix.$message; + $this->debugLog[] = implode(' -> ',$this->debugLogStack).' -> '.$message; } } // function _writeDebug() @@ -2857,6 +3063,7 @@ class PHPExcel_Calculation { // trigger an error, but nicely, if need be private function _raiseFormulaError($errorMessage) { $this->formulaError = $errorMessage; + echo '_raiseFormulaError message is '.$errorMessage.'
'; if (!$this->suppressFormulaErrors) throw new Exception($errorMessage); trigger_error($errorMessage, E_USER_ERROR); } // function _raiseFormulaError() @@ -2865,20 +3072,18 @@ class PHPExcel_Calculation { /** * Extract range values * - * @param string $pRange String based range representation + * @param string &$pRange String based range representation * @param PHPExcel_Worksheet $pSheet Worksheet * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. * @throws Exception */ - public function extractCellRange($pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { + public function extractCellRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { // Return value - $returnValue = array ( ); + $returnValue = array (); // echo 'extractCellRange('.$pRange.')
'; - // Worksheet given? if (!is_null($pSheet)) { - // Worksheet reference? -// echo 'Current sheet name is '.$pSheet->getTitle().'
'; +// echo 'Passed sheet name is '.$pSheet->getTitle().'
'; // echo 'Range reference is '.$pRange.'
'; if (strpos ($pRange, '!') !== false) { // echo '$pRange reference includes sheet reference
'; @@ -2891,16 +3096,26 @@ class PHPExcel_Calculation { // Extract range $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); + $pRange = $pSheet->getTitle().'!'.$pRange; if (count($aReferences) == 1) { - return $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); - } + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]); + if ($pSheet->cellExists($aReferences[0])) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } else { + // Extract cell data + foreach ($aReferences as $reference) { + // Extract range + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); - // Extract cell data - foreach ($aReferences as $reference) { - // Extract range - list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); - - $returnValue[$currentCol][$currentRow] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + if ($pSheet->cellExists($reference)) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } } } @@ -2912,19 +3127,17 @@ class PHPExcel_Calculation { /** * Extract range values * - * @param string $pRange String based range representation + * @param string &$pRange String based range representation * @param PHPExcel_Worksheet $pSheet Worksheet * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. * @throws Exception */ - public function extractNamedRange($pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { + public function extractNamedRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { // Return value - $returnValue = array ( ); + $returnValue = array (); // echo 'extractNamedRange('.$pRange.')
'; - // Worksheet given? if (!is_null($pSheet)) { - // Worksheet reference? // echo 'Current sheet name is '.$pSheet->getTitle().'
'; // echo 'Range reference is '.$pRange.'
'; if (strpos ($pRange, '!') !== false) { @@ -2949,29 +3162,33 @@ class PHPExcel_Calculation { return $returnValue; } } + } else { + return PHPExcel_Calculation_Functions::REF(); } // Extract range $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); if (count($aReferences) == 1) { - return $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]); + if ($pSheet->cellExists($aReferences[0])) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } else { + // Extract cell data + foreach ($aReferences as $reference) { + // Extract range + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); +// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'
'; + if ($pSheet->cellExists($reference)) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } } - - // Extract cell data - foreach ($aReferences as $reference) { - // Extract range - list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); -// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'
'; - $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); - } -// print_r($returnValue); -// echo '
'; - $returnValue = array_values($returnValue); - foreach($returnValue as &$rr) { - $rr = array_values($rr); - } - unset($rr); -// print_r($returnValue); +// print_r($returnValue); // echo '
'; } @@ -2988,7 +3205,7 @@ class PHPExcel_Calculation { */ public function isImplemented($pFunction = '') { $pFunction = strtoupper ($pFunction); - if (isset ($this->_PHPExcelFunctions[$pFunction])) { + if (isset($this->_PHPExcelFunctions[$pFunction])) { return ($this->_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY'); } else { return false; @@ -3025,15 +3242,7 @@ class PHPExcel_Calculation { * @return array */ public function listFunctionNames() { - // Return value - $returnValue = array(); - // Loop functions - foreach ($this->_PHPExcelFunctions as $functionName => $function) { - $returnValue[] = $functionName; - } - - // Return - return $returnValue; + return array_keys($this->_PHPExcelFunctions); } // function listFunctionNames() } // class PHPExcel_Calculation @@ -3047,27 +3256,35 @@ class PHPExcel_Token_Stack { private $_stack = array(); private $_count = 0; + public function count() { return $this->_count; - } + } // function count() + + + public function push($type,$value,$reference=null) { + $this->_stack[$this->_count++] = array('type' => $type, + 'value' => $value, + 'reference' => $reference + ); + } // function push() - public function push($value) { - $this->_stack[$this->_count++] = $value; - } public function pop() { if ($this->_count > 0) { return $this->_stack[--$this->_count]; } return null; - } + } // function pop() + public function last($n=1) { if ($this->_count-$n < 0) { return null; } return $this->_stack[$this->_count-$n]; - } + } // function last() + function __construct() { } diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Exception.php b/libraries/PHPExcel/PHPExcel/Calculation/Exception.php index 36ea5e08a..84cf09d79 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Exception.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Exception.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Exception extends Exception { /** diff --git a/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php b/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php index 734c4a611..48475df5c 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/ExceptionHandler.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ @@ -41,7 +41,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Exception.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_ExceptionHandler { /** diff --git a/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php b/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php index 648e93983..d6bf785ad 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/FormulaParser.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -65,7 +65,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/FormulaToken.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_FormulaParser { /* Character constants */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php b/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php index dff57675c..091e69d0b 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/FormulaToken.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ PARTLY BASED ON: * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_FormulaToken { /* Token types */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Function.php b/libraries/PHPExcel/PHPExcel/Calculation/Function.php index 7b0c6c175..6ea8aea10 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Function.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Function.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Function { /* Function categories */ diff --git a/libraries/PHPExcel/PHPExcel/Calculation/Functions.php b/libraries/PHPExcel/PHPExcel/Calculation/Functions.php index 8d6ca3d05..2ba67fd77 100644 --- a/libraries/PHPExcel/PHPExcel/Calculation/Functions.php +++ b/libraries/PHPExcel/PHPExcel/Calculation/Functions.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -38,14 +38,21 @@ define('LOG_GAMMA_X_MAX_VALUE', 2.55e305); /** SQRT2PI */ define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099); +/** 2 / PI */ +define('M_2DIVPI', 0.63661977236758134307553505349006); + /** XMININ */ define('XMININ', 2.23e-308); /** MAX_ITERATIONS */ -define('MAX_ITERATIONS', 150); +define('MAX_ITERATIONS', 256); +/** FINANCIAL_MAX_ITERATIONS */ +define('FINANCIAL_MAX_ITERATIONS', 128); /** PRECISION */ define('PRECISION', 8.88E-016); +/** FINANCIAL_PRECISION */ +define('FINANCIAL_PRECISION', 1.0e-08); /** EULER */ define('EULER', 2.71828182845904523536); @@ -67,6 +74,9 @@ if (!defined('PHPEXCEL_ROOT')) { /** PHPExcel_Cell */ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; +/** PHPExcel_Calculation */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation.php'; + /** PHPExcel_Cell_DataType */ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; @@ -86,7 +96,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/trendClass.php'; * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Functions { @@ -271,21 +281,48 @@ class PHPExcel_Calculation_Functions { } // function REF() + /** + * VALUE + * + * @access public + * @category Error Returns + * @return string #VALUE! + */ + public static function VALUE() { + return self::$_errorCodes['value']; + } // function VALUE() + + + private static function isMatrixValue($idx) { + return ((substr_count($idx,'.') <= 1) || (preg_match('/\.[A-Z]/',$idx) > 0)); + } + + + private static function isValue($idx) { + return (substr_count($idx,'.') == 0); + } + + + private static function isCellValue($idx) { + return (substr_count($idx,'.') > 1); + } + + /** * LOGICAL_AND * * Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE. * * Excel Function: - * AND(logical1[,logical2[, ...]]) + * =AND(logical1[,logical2[, ...]]) * * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays * or references that contain logical values. * - * Booleans arguments are treated as True or False as appropriate + * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds the value TRUE or FALSE, - * holds the value TRUE or FALSE, in which case it is evaluated as a boolean + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value * * @access public * @category Logical Functions @@ -303,10 +340,8 @@ class PHPExcel_Calculation_Functions { // Is it a boolean value? if (is_bool($arg)) { $returnValue = $returnValue && $arg; - ++$argCount; } elseif ((is_numeric($arg)) && (!is_string($arg))) { $returnValue = $returnValue && ($arg != 0); - ++$argCount; } elseif (is_string($arg)) { $arg = strtoupper($arg); if ($arg == 'TRUE') { @@ -317,8 +352,8 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } $returnValue = $returnValue && ($arg != 0); - ++$argCount; } + ++$argCount; } // Return @@ -335,15 +370,15 @@ class PHPExcel_Calculation_Functions { * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE. * * Excel Function: - * OR(logical1[,logical2[, ...]]) + * =OR(logical1[,logical2[, ...]]) * * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays * or references that contain logical values. * - * Booleans arguments are treated as True or False as appropriate + * Boolean arguments are treated as True or False as appropriate * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False - * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string - * holds the value TRUE or FALSE, in which case it is evaluated as a boolean + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value * * @access public * @category Logical Functions @@ -361,10 +396,8 @@ class PHPExcel_Calculation_Functions { // Is it a boolean value? if (is_bool($arg)) { $returnValue = $returnValue || $arg; - ++$argCount; } elseif ((is_numeric($arg)) && (!is_string($arg))) { $returnValue = $returnValue || ($arg != 0); - ++$argCount; } elseif (is_string($arg)) { $arg = strtoupper($arg); if ($arg == 'TRUE') { @@ -375,8 +408,8 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['value']; } $returnValue = $returnValue || ($arg != 0); - ++$argCount; } + ++$argCount; } // Return @@ -393,7 +426,7 @@ class PHPExcel_Calculation_Functions { * Returns the boolean FALSE. * * Excel Function: - * FALSE() + * =FALSE() * * @access public * @category Logical Functions @@ -410,7 +443,7 @@ class PHPExcel_Calculation_Functions { * Returns the boolean TRUE. * * Excel Function: - * TRUE() + * =TRUE() * * @access public * @category Logical Functions @@ -427,7 +460,14 @@ class PHPExcel_Calculation_Functions { * Returns the boolean inverse of the argument. * * Excel Function: - * NOT(logical) + * =NOT(logical) + * + * The argument must evaluate to a logical value such as TRUE or FALSE + * + * Boolean arguments are treated as True or False as appropriate + * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value * * @access public * @category Logical Functions @@ -435,6 +475,18 @@ class PHPExcel_Calculation_Functions { * @return boolean The boolean inverse of the argument. */ public static function LOGICAL_NOT($logical) { + $logical = self::flattenSingleValue($logical); + if (is_string($logical)) { + $logical = strtoupper($logical); + if ($logical == 'TRUE') { + return False; + } elseif ($logical == 'FALSE') { + return True; + } else { + return self::$_errorCodes['value']; + } + } + return !$logical; } // function LOGICAL_NOT() @@ -445,7 +497,7 @@ class PHPExcel_Calculation_Functions { * Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE. * * Excel Function: - * IF(condition[,returnIfTrue[,returnIfFalse]]) + * =IF(condition[,returnIfTrue[,returnIfFalse]]) * * Condition is any value or expression that can be evaluated to TRUE or FALSE. * For example, A10=100 is a logical expression; if the value in cell A10 is equal to 100, @@ -464,17 +516,17 @@ class PHPExcel_Calculation_Functions { * If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned. * ReturnIfFalse can be another formula. * + * @access public + * @category Logical Functions * @param mixed $condition Condition to evaluate * @param mixed $returnIfTrue Value to return when condition is true - * @param mixed $returnIfFalse Value to return when condition is false + * @param mixed $returnIfFalse Optional value to return when condition is false * @return mixed The value of returnIfTrue or returnIfFalse determined by condition */ public static function STATEMENT_IF($condition = true, $returnIfTrue = 0, $returnIfFalse = False) { - $condition = self::flattenSingleValue($condition); - $returnIfTrue = self::flattenSingleValue($returnIfTrue); - $returnIfFalse = self::flattenSingleValue($returnIfFalse); - if (is_null($returnIfTrue)) { $returnIfTrue = 0; } - if (is_null($returnIfFalse)) { $returnIfFalse = 0; } + $condition = (is_null($condition)) ? True : (boolean) self::flattenSingleValue($condition); + $returnIfTrue = (is_null($returnIfTrue)) ? 0 : self::flattenSingleValue($returnIfTrue); + $returnIfFalse = (is_null($returnIfFalse)) ? False : self::flattenSingleValue($returnIfFalse); return ($condition ? $returnIfTrue : $returnIfFalse); } // function STATEMENT_IF() @@ -483,12 +535,20 @@ class PHPExcel_Calculation_Functions { /** * STATEMENT_IFERROR * - * @param mixed $value Value to check , is also value when no error - * @param mixed $errorpart Value when error - * @return mixed + * Excel Function: + * =IFERROR(testValue,errorpart) + * + * @access public + * @category Logical Functions + * @param mixed $testValue Value to check, is also the value returned when no error + * @param mixed $errorpart Value to return when testValue is an error condition + * @return mixed The value of errorpart or testValue determined by error condition */ - public static function STATEMENT_IFERROR($value = '', $errorpart = '') { - return self::STATEMENT_IF(self::IS_ERROR($value), $errorpart, $value); + public static function STATEMENT_IFERROR($testValue = '', $errorpart = '') { + $testValue = (is_null($testValue)) ? '' : self::flattenSingleValue($testValue); + $errorpart = (is_null($errorpart)) ? '' : self::flattenSingleValue($errorpart); + + return self::STATEMENT_IF(self::IS_ERROR($testValue), $errorpart, $testValue); } // function STATEMENT_IFERROR() @@ -542,7 +602,7 @@ class PHPExcel_Calculation_Functions { */ public static function LOG_BASE($number, $base=10) { $number = self::flattenSingleValue($number); - $base = self::flattenSingleValue($base); + $base = (is_null($base)) ? 10 : (float) self::flattenSingleValue($base); return log($number, $base); } // function LOG_BASE() @@ -596,12 +656,12 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { - $returnValue += pow($arg,2); + $returnValue += ($arg * $arg); } } @@ -627,7 +687,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -666,7 +726,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -706,7 +766,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -785,9 +845,9 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); // Calculate - $n = array_pop($aArgs); + $entry = array_pop($aArgs); - if ((is_numeric($n)) && (!is_string($n))) { + if ((is_numeric($entry)) && (!is_string($entry))) { $mArgs = array(); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -796,12 +856,12 @@ class PHPExcel_Calculation_Functions { } } $count = self::COUNT($mArgs); - $n = floor(--$n); - if (($n < 0) || ($n >= $count) || ($count == 0)) { + $entry = floor(--$entry); + if (($entry < 0) || ($entry >= $count) || ($count == 0)) { return self::$_errorCodes['num']; } sort($mArgs); - return $mArgs[$n]; + return $mArgs[$entry]; } return self::$_errorCodes['value']; } // function SMALL() @@ -825,7 +885,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = null; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -905,9 +965,9 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); // Calculate - $n = floor(array_pop($aArgs)); + $entry = floor(array_pop($aArgs)); - if ((is_numeric($n)) && (!is_string($n))) { + if ((is_numeric($entry)) && (!is_string($entry))) { $mArgs = array(); foreach ($aArgs as $arg) { // Is it a numeric value? @@ -916,12 +976,12 @@ class PHPExcel_Calculation_Functions { } } $count = self::COUNT($mArgs); - $n = floor(--$n); - if (($n < 0) || ($n >= $count) || ($count == 0)) { + $entry = floor(--$entry); + if (($entry < 0) || ($entry >= $count) || ($count == 0)) { return self::$_errorCodes['num']; } rsort($mArgs); - return $mArgs[$n]; + return $mArgs[$entry]; } return self::$_errorCodes['value']; } // function LARGE() @@ -1025,11 +1085,12 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments - $aArgs = self::flattenArray(func_get_args()); - foreach ($aArgs as $arg) { - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { - $arg = (int) $arg; + // Loop through arguments + $aArgs = self::flattenArrayIndexed(func_get_args()); + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { @@ -1059,7 +1120,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { // Is it a blank cell? @@ -1123,9 +1184,15 @@ class PHPExcel_Calculation_Functions { $returnValue = 0; $aArgs = self::flattenArray($aArgs); + $condition = self::flattenSingleValue($condition); if (!in_array($condition{0},array('>', '<', '='))) { if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } $condition = '='.$condition; + } else { + preg_match('/([<>=]+)(.*)/',$condition,$matches); + list(,$operator,$operand) = $matches; + if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } + $condition = $operator.$operand; } // Loop through arguments foreach ($aArgs as $arg) { @@ -1168,6 +1235,11 @@ class PHPExcel_Calculation_Functions { if (!in_array($condition{0},array('>', '<', '='))) { if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } $condition = '='.$condition; + } else { + preg_match('/([<>=]+)(.*)/',$condition,$matches); + list(,$operator,$operand) = $matches; + if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } + $condition = $operator.$operand; } // Loop through arguments foreach ($aArgs as $key => $arg) { @@ -1198,14 +1270,13 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function AVERAGE() { - // Return value - $returnValue = 0; + $aArgs = self::flattenArrayIndexed(func_get_args()); + $returnValue = $aCount = 0; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); - $aCount = 0; - foreach ($aArgs as $arg) { - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { $arg = (integer) $arg; } // Is it a numeric value? @@ -1246,21 +1317,25 @@ class PHPExcel_Calculation_Functions { $returnValue = null; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $aCount = 0; - foreach ($aArgs as $arg) { - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = $arg; + } else { + $returnValue += $arg; + } + ++$aCount; } - if (is_null($returnValue)) { - $returnValue = $arg; - } else { - $returnValue += $arg; - } - ++$aCount; } } @@ -1402,18 +1477,19 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function DEVSQ() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGE(func_get_args()); - if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - + $aMean = self::AVERAGE($aArgs); + if ($aMean != self::$_errorCodes['divisionbyzero']) { $aCount = -1; - foreach ($aArgs as $arg) { + foreach ($aArgs as $k => $arg) { // Is it a numeric value? - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { - $arg = (int) $arg; + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; } if ((is_numeric($arg)) && (!is_string($arg))) { if (is_null($returnValue)) { @@ -1451,7 +1527,7 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function AVEDEV() { - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); // Return value $returnValue = null; @@ -1459,8 +1535,9 @@ class PHPExcel_Calculation_Functions { $aMean = self::AVERAGE($aArgs); if ($aMean != self::$_errorCodes['divisionbyzero']) { $aCount = 0; - foreach ($aArgs as $arg) { - if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { $arg = (integer) $arg; } // Is it a numeric value? @@ -1475,7 +1552,10 @@ class PHPExcel_Calculation_Functions { } // Return - return $returnValue / $aCount ; + if ($aCount == 0) { + return self::$_errorCodes['divisionbyzero']; + } + return $returnValue / $aCount; } return self::$_errorCodes['num']; } // function AVEDEV() @@ -1497,9 +1577,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function GEOMEAN() { - $aMean = self::PRODUCT(func_get_args()); + $aArgs = self::flattenArray(func_get_args()); + + $aMean = self::PRODUCT($aArgs); if (is_numeric($aMean) && ($aMean > 0)) { - $aArgs = self::flattenArray(func_get_args()); $aCount = self::COUNT($aArgs) ; if (self::MIN($aArgs) > 0) { return pow($aMean, (1 / $aCount)); @@ -1617,15 +1698,19 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEV() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGE(func_get_args()); + $aMean = self::AVERAGE($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = -1; - foreach ($aArgs as $arg) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { if (is_null($returnValue)) { @@ -1660,28 +1745,32 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEVA() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGEA(func_get_args()); + $aMean = self::AVERAGEA($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = -1; - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; } - if (is_null($returnValue)) { - $returnValue = pow(($arg - $aMean),2); - } else { - $returnValue += pow(($arg - $aMean),2); - } - ++$aCount; } } @@ -1708,15 +1797,19 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEVP() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGE(func_get_args()); + $aMean = self::AVERAGE($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = 0; - foreach ($aArgs as $arg) { + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { if (is_null($returnValue)) { @@ -1751,28 +1844,32 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STDEVPA() { + $aArgs = self::flattenArrayIndexed(func_get_args()); + // Return value $returnValue = null; - $aMean = self::AVERAGEA(func_get_args()); + $aMean = self::AVERAGEA($aArgs); if (!is_null($aMean)) { - $aArgs = self::flattenArray(func_get_args()); - $aCount = 0; - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; } - if (is_null($returnValue)) { - $returnValue = pow(($arg - $aMean),2); - } else { - $returnValue += pow(($arg - $aMean),2); - } - ++$aCount; } } @@ -1808,6 +1905,7 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); $aCount = 0; foreach ($aArgs as $arg) { + if (is_bool($arg)) { $arg = (integer) $arg; } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { $summerA += ($arg * $arg); @@ -1818,8 +1916,8 @@ class PHPExcel_Calculation_Functions { // Return if ($aCount > 1) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); } return $returnValue; @@ -1846,26 +1944,33 @@ class PHPExcel_Calculation_Functions { $summerA = $summerB = 0; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $aCount = 0; - foreach ($aArgs as $arg) { - // Is it a numeric value? + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && + (self::isValue($k))) { + return self::$_errorCodes['value']; + } elseif ((is_string($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; } - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; } } // Return if ($aCount > 1) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); } return $returnValue; @@ -1895,6 +2000,7 @@ class PHPExcel_Calculation_Functions { $aArgs = self::flattenArray(func_get_args()); $aCount = 0; foreach ($aArgs as $arg) { + if (is_bool($arg)) { $arg = (integer) $arg; } // Is it a numeric value? if ((is_numeric($arg)) && (!is_string($arg))) { $summerA += ($arg * $arg); @@ -1905,8 +2011,8 @@ class PHPExcel_Calculation_Functions { // Return if ($aCount > 0) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * $aCount); } return $returnValue; @@ -1933,26 +2039,33 @@ class PHPExcel_Calculation_Functions { $summerA = $summerB = 0; // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $aCount = 0; - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { - if (is_bool($arg)) { - $arg = (integer) $arg; - } elseif (is_string($arg)) { - $arg = 0; + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && + (self::isValue($k))) { + return self::$_errorCodes['value']; + } elseif ((is_string($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; } - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; } } // Return if ($aCount > 0) { - $summerA = $summerA * $aCount; - $summerB = ($summerB * $summerB); + $summerA *= $aCount; + $summerB *= $summerB; $returnValue = ($summerA - $summerB) / ($aCount * $aCount); } return $returnValue; @@ -1972,7 +2085,7 @@ class PHPExcel_Calculation_Functions { public static function RANK($value,$valueSet,$order=0) { $value = self::flattenSingleValue($value); $valueSet = self::flattenArray($valueSet); - $order = self::flattenSingleValue($order); + $order = (is_null($order)) ? 0 : (integer) self::flattenSingleValue($order); foreach($valueSet as $key => $valueEntry) { if (!is_numeric($valueEntry)) { @@ -2005,9 +2118,9 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function PERCENTRANK($valueSet,$value,$significance=3) { - $valueSet = self::flattenArray($valueSet); - $value = self::flattenSingleValue($value); - $significance = self::flattenSingleValue($significance); + $valueSet = self::flattenArray($valueSet); + $value = self::flattenSingleValue($value); + $significance = (is_null($significance)) ? 3 : (integer) self::flattenSingleValue($significance); foreach($valueSet as $key => $valueEntry) { if (!is_numeric($valueEntry)) { @@ -2040,20 +2153,29 @@ class PHPExcel_Calculation_Functions { } // function PERCENTRANK() - private static function _checkTrendArray($values) { - foreach($values as $key => $value) { - if ((is_bool($value)) || ((is_string($value)) && (trim($value) == ''))) { - unset($values[$key]); - } elseif (is_string($value)) { - if (is_numeric($value)) { - $values[$key] = (float) $value; - } else { - unset($values[$key]); - } + private static function _checkTrendArrays(&$array1,&$array2) { + if (!is_array($array1)) { $array1 = array($array1); } + if (!is_array($array2)) { $array2 = array($array2); } + + $array1 = self::flattenArray($array1); + $array2 = self::flattenArray($array2); + foreach($array1 as $key => $value) { + if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { + unset($array1[$key]); + unset($array2[$key]); } } - return $values; - } // function _checkTrendArray() + foreach($array2 as $key => $value) { + if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { + unset($array1[$key]); + unset($array2[$key]); + } + } + $array1 = array_merge($array1); + $array2 = array_merge($array2); + + return True; + } // function _checkTrendArrays() /** @@ -2066,12 +2188,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function INTERCEPT($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2095,12 +2215,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function RSQ($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2124,12 +2242,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function SLOPE($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2153,12 +2269,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function STEYX($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2182,12 +2296,10 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function COVAR($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2210,13 +2322,14 @@ class PHPExcel_Calculation_Functions { * @param array of mixed Data Series X * @return float */ - public static function CORREL($yValues,$xValues) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - - $yValues = self::_checkTrendArray($yValues); + public static function CORREL($yValues,$xValues=null) { + if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) { + return self::$_errorCodes['value']; + } + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2242,21 +2355,22 @@ class PHPExcel_Calculation_Functions { * @param boolean A logical value specifying whether to return additional regression statistics. * @return array */ - public static function LINEST($yValues,$xValues,$const=True,$stats=False) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - $const = (boolean) self::flattenSingleValue($const); - $stats = (boolean) self::flattenSingleValue($stats); + public static function LINEST($yValues,$xValues=null,$const=True,$stats=False) { + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); + $stats = (is_null($stats)) ? False : (boolean) self::flattenSingleValue($stats); + if (is_null($xValues)) $xValues = range(1,count(self::flattenArray($yValues))); - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { return self::$_errorCodes['na']; } elseif ($yValueCount == 1) { - return self::$_errorCodes['divisionbyzero']; + return 0; } $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const); @@ -2294,21 +2408,28 @@ class PHPExcel_Calculation_Functions { * @param boolean A logical value specifying whether to return additional regression statistics. * @return array */ - public static function LOGEST($yValues,$xValues,$const=True,$stats=False) { - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - $const = (boolean) self::flattenSingleValue($const); - $stats = (boolean) self::flattenSingleValue($stats); + public static function LOGEST($yValues,$xValues=null,$const=True,$stats=False) { + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); + $stats = (is_null($stats)) ? False : (boolean) self::flattenSingleValue($stats); + if (is_null($xValues)) $xValues = range(1,count(self::flattenArray($yValues))); - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); + foreach($yValues as $value) { + if ($value <= 0.0) { + return self::$_errorCodes['num']; + } + } + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { return self::$_errorCodes['na']; } elseif ($yValueCount == 1) { - return self::$_errorCodes['divisionbyzero']; + return 1; } $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const); @@ -2346,16 +2467,14 @@ class PHPExcel_Calculation_Functions { */ public static function FORECAST($xValue,$yValues,$xValues) { $xValue = self::flattenSingleValue($xValue); - $yValues = self::flattenArray($yValues); - $xValues = self::flattenArray($xValues); - if (!is_numeric($xValue)) { return self::$_errorCodes['value']; } - $yValues = self::_checkTrendArray($yValues); + if (!self::_checkTrendArrays($yValues,$xValues)) { + return self::$_errorCodes['value']; + } $yValueCount = count($yValues); - $xValues = self::_checkTrendArray($xValues); $xValueCount = count($xValues); if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { @@ -2384,7 +2503,7 @@ class PHPExcel_Calculation_Functions { $yValues = self::flattenArray($yValues); $xValues = self::flattenArray($xValues); $newValues = self::flattenArray($newValues); - $const = (boolean) self::flattenSingleValue($const); + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const); if (count($newValues) == 0) { @@ -2415,7 +2534,7 @@ class PHPExcel_Calculation_Functions { $yValues = self::flattenArray($yValues); $xValues = self::flattenArray($xValues); $newValues = self::flattenArray($newValues); - $const = (boolean) self::flattenSingleValue($const); + $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const); if (count($newValues) == 0) { @@ -2438,6 +2557,7 @@ class PHPExcel_Calculation_Functions { public static function ROMAN($aValue, $style=0) { $aValue = (integer) self::flattenSingleValue($aValue); + $style = (is_null($style)) ? 0 : (integer) self::flattenSingleValue($style); if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) { return self::$_errorCodes['value']; } @@ -2464,14 +2584,14 @@ class PHPExcel_Calculation_Functions { /** - * SUBTOTAL + * SUBTOTAL * - * Returns a subtotal in a list or database. + * Returns a subtotal in a list or database. * - * @param int the number 1 to 11 that specifies which function to + * @param int the number 1 to 11 that specifies which function to * use in calculating subtotals within a list. - * @param array of mixed Data Series - * @return float + * @param array of mixed Data Series + * @return float */ public static function SUBTOTAL() { $aArgs = self::flattenArray(func_get_args()); @@ -2521,12 +2641,12 @@ class PHPExcel_Calculation_Functions { /** - * SQRTPI + * SQRTPI * - * Returns the square root of (number * pi). + * Returns the square root of (number * pi). * - * @param float $number Number - * @return float Square Root of Number * Pi + * @param float $number Number + * @return float Square Root of Number * Pi */ public static function SQRTPI($number) { $number = self::flattenSingleValue($number); @@ -2535,19 +2655,19 @@ class PHPExcel_Calculation_Functions { if ($number < 0) { return self::$_errorCodes['num']; } - return sqrt($number * pi()) ; + return sqrt($number * M_PI) ; } return self::$_errorCodes['value']; } // function SQRTPI() /** - * FACT + * FACT * - * Returns the factorial of a number. + * Returns the factorial of a number. * - * @param float $factVal Factorial Value - * @return int Factorial + * @param float $factVal Factorial Value + * @return int Factorial */ public static function FACT($factVal) { $factVal = self::flattenSingleValue($factVal); @@ -2562,6 +2682,7 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } } + $factorial = 1; while ($factLoop > 1) { $factorial *= $factLoop--; @@ -2573,12 +2694,12 @@ class PHPExcel_Calculation_Functions { /** - * FACTDOUBLE + * FACTDOUBLE * - * Returns the double factorial of a number. + * Returns the double factorial of a number. * - * @param float $factVal Factorial Value - * @return int Double Factorial + * @param float $factVal Factorial Value + * @return int Double Factorial */ public static function FACTDOUBLE($factVal) { $factLoop = floor(self::flattenSingleValue($factVal)); @@ -2599,12 +2720,12 @@ class PHPExcel_Calculation_Functions { /** - * MULTINOMIAL + * MULTINOMIAL * - * Returns the ratio of the factorial of a sum of values to the product of factorials. + * Returns the ratio of the factorial of a sum of values to the product of factorials. * - * @param array of mixed Data Series - * @return float + * @param array of mixed Data Series + * @return float */ public static function MULTINOMIAL() { // Loop through arguments @@ -2634,13 +2755,13 @@ class PHPExcel_Calculation_Functions { /** - * CEILING + * CEILING * - * Returns number rounded up, away from zero, to the nearest multiple of significance. + * Returns number rounded up, away from zero, to the nearest multiple of significance. * - * @param float $number Number to round - * @param float $significance Significance - * @return float Rounded Number + * @param float $number Number to round + * @param float $significance Significance + * @return float Rounded Number */ public static function CEILING($number,$significance=null) { $number = self::flattenSingleValue($number); @@ -2665,12 +2786,12 @@ class PHPExcel_Calculation_Functions { /** - * EVEN + * EVEN * - * Returns number rounded up to the nearest even integer. + * Returns number rounded up to the nearest even integer. * - * @param float $number Number to round - * @return int Rounded Number + * @param float $number Number to round + * @return int Rounded Number */ public static function EVEN($number) { $number = self::flattenSingleValue($number); @@ -2684,12 +2805,12 @@ class PHPExcel_Calculation_Functions { /** - * ODD + * ODD * - * Returns number rounded up to the nearest odd integer. + * Returns number rounded up to the nearest odd integer. * - * @param float $number Number to round - * @return int Rounded Number + * @param float $number Number to round + * @return int Rounded Number */ public static function ODD($number) { $number = self::flattenSingleValue($number); @@ -2728,13 +2849,13 @@ class PHPExcel_Calculation_Functions { /** - * ROUNDUP + * ROUNDUP * - * Rounds a number up to a specified number of decimal places + * Rounds a number up to a specified number of decimal places * - * @param float $number Number to round - * @param int $digits Number of digits to which you want to round $number - * @return float Rounded Number + * @param float $number Number to round + * @param int $digits Number of digits to which you want to round $number + * @return float Rounded Number */ public static function ROUNDUP($number,$digits) { $number = self::flattenSingleValue($number); @@ -2753,13 +2874,13 @@ class PHPExcel_Calculation_Functions { /** - * ROUNDDOWN + * ROUNDDOWN * - * Rounds a number down to a specified number of decimal places + * Rounds a number down to a specified number of decimal places * - * @param float $number Number to round - * @param int $digits Number of digits to which you want to round $number - * @return float Rounded Number + * @param float $number Number to round + * @param int $digits Number of digits to which you want to round $number + * @return float Rounded Number */ public static function ROUNDDOWN($number,$digits) { $number = self::flattenSingleValue($number); @@ -2778,13 +2899,13 @@ class PHPExcel_Calculation_Functions { /** - * MROUND + * MROUND * - * Rounds a number to the nearest multiple of a specified value + * Rounds a number to the nearest multiple of a specified value * - * @param float $number Number to round - * @param int $multiple Multiple to which you want to round $number - * @return float Rounded Number + * @param float $number Number to round + * @param int $multiple Multiple to which you want to round $number + * @return float Rounded Number */ public static function MROUND($number,$multiple) { $number = self::flattenSingleValue($number); @@ -2805,13 +2926,13 @@ class PHPExcel_Calculation_Functions { /** - * SIGN + * SIGN * - * Determines the sign of a number. Returns 1 if the number is positive, zero (0) - * if the number is 0, and -1 if the number is negative. + * Determines the sign of a number. Returns 1 if the number is positive, zero (0) + * if the number is 0, and -1 if the number is negative. * - * @param float $number Number to round - * @return int sign value + * @param float $number Number to round + * @return int sign value */ public static function SIGN($number) { $number = self::flattenSingleValue($number); @@ -2827,13 +2948,13 @@ class PHPExcel_Calculation_Functions { /** - * FLOOR + * FLOOR * - * Rounds number down, toward zero, to the nearest multiple of significance. + * Rounds number down, toward zero, to the nearest multiple of significance. * - * @param float $number Number to round - * @param float $significance Significance - * @return float Rounded Number + * @param float $number Number to round + * @param float $significance Significance + * @return float Rounded Number */ public static function FLOOR($number,$significance=null) { $number = self::flattenSingleValue($number); @@ -2875,6 +2996,7 @@ class PHPExcel_Calculation_Functions { $numInSet = self::flattenSingleValue($numInSet); if ((is_numeric($numObjs)) && (is_numeric($numInSet))) { + $numInSet = floor($numInSet); if ($numObjs < $numInSet) { return self::$_errorCodes['num']; } @@ -2911,21 +3033,21 @@ class PHPExcel_Calculation_Functions { /** - * SERIESSUM + * SERIESSUM * - * Returns the sum of a power series + * Returns the sum of a power series * - * @param float $x Input value to the power series - * @param float $n Initial power to which you want to raise $x - * @param float $m Step by which to increase $n for each term in the series - * @param array of mixed Data Series - * @return float + * @param float $x Input value to the power series + * @param float $n Initial power to which you want to raise $x + * @param float $m Step by which to increase $n for each term in the series + * @param array of mixed Data Series + * @return float */ public static function SERIESSUM() { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); $x = array_shift($aArgs); @@ -2951,14 +3073,14 @@ class PHPExcel_Calculation_Functions { /** - * STANDARDIZE + * STANDARDIZE * - * Returns a normalized value from a distribution characterized by mean and standard_dev. + * Returns a normalized value from a distribution characterized by mean and standard_dev. * - * @param float $value Value to normalize - * @param float $mean Mean Value - * @param float $stdDev Standard Deviation - * @return float Standardized value + * @param float $value Value to normalize + * @param float $mean Mean Value + * @param float $stdDev Standard Deviation + * @return float Standardized value */ public static function STANDARDIZE($value,$mean,$stdDev) { $value = self::flattenSingleValue($value); @@ -3001,12 +3123,12 @@ class PHPExcel_Calculation_Functions { /** - * LCM + * LCM * - * Returns the lowest common multiplier of a series of numbers + * Returns the lowest common multiplier of a series of numbers * - * @param $array Values to calculate the Lowest Common Multiplier - * @return int Lowest Common Multiplier + * @param $array Values to calculate the Lowest Common Multiplier + * @return int Lowest Common Multiplier */ public static function LCM() { $aArgs = self::flattenArray(func_get_args()); @@ -3046,12 +3168,12 @@ class PHPExcel_Calculation_Functions { /** - * GCD + * GCD * - * Returns the greatest common divisor of a series of numbers + * Returns the greatest common divisor of a series of numbers * - * @param $array Values to calculate the Greatest Common Divisor - * @return int Greatest Common Divisor + * @param $array Values to calculate the Greatest Common Divisor + * @return int Greatest Common Divisor */ public static function GCD() { $aArgs = self::flattenArray(func_get_args()); @@ -3108,21 +3230,21 @@ class PHPExcel_Calculation_Functions { /** - * BINOMDIST + * BINOMDIST * - * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with - * a fixed number of tests or trials, when the outcomes of any trial are only success or failure, - * when trials are independent, and when the probability of success is constant throughout the - * experiment. For example, BINOMDIST can calculate the probability that two of the next three - * babies born are male. + * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with + * a fixed number of tests or trials, when the outcomes of any trial are only success or failure, + * when trials are independent, and when the probability of success is constant throughout the + * experiment. For example, BINOMDIST can calculate the probability that two of the next three + * babies born are male. * - * @param float $value Number of successes in trials - * @param float $trials Number of trials - * @param float $probability Probability of success on each trial - * @param boolean $cumulative - * @return float + * @param float $value Number of successes in trials + * @param float $trials Number of trials + * @param float $probability Probability of success on each trial + * @param boolean $cumulative + * @return float * - * @todo Cumulative distribution function + * @todo Cumulative distribution function * */ public static function BINOMDIST($value, $trials, $probability, $cumulative) { @@ -3154,18 +3276,18 @@ class PHPExcel_Calculation_Functions { /** - * NEGBINOMDIST + * NEGBINOMDIST * - * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that - * there will be number_f failures before the number_s-th success, when the constant - * probability of a success is probability_s. This function is similar to the binomial - * distribution, except that the number of successes is fixed, and the number of trials is - * variable. Like the binomial, trials are assumed to be independent. + * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that + * there will be number_f failures before the number_s-th success, when the constant + * probability of a success is probability_s. This function is similar to the binomial + * distribution, except that the number of successes is fixed, and the number of trials is + * variable. Like the binomial, trials are assumed to be independent. * - * @param float $failures Number of Failures - * @param float $successes Threshold number of Successes - * @param float $probability Probability of success on each trial - * @return float + * @param float $failures Number of Failures + * @param float $successes Threshold number of Successes + * @param float $probability Probability of success on each trial + * @return float * */ public static function NEGBINOMDIST($failures, $successes, $probability) { @@ -3192,17 +3314,17 @@ class PHPExcel_Calculation_Functions { /** - * CRITBINOM + * CRITBINOM * - * Returns the smallest value for which the cumulative binomial distribution is greater - * than or equal to a criterion value + * Returns the smallest value for which the cumulative binomial distribution is greater + * than or equal to a criterion value * - * See http://support.microsoft.com/kb/828117/ for details of the algorithm used + * See http://support.microsoft.com/kb/828117/ for details of the algorithm used * - * @param float $trials number of Bernoulli trials - * @param float $probability probability of a success on each trial - * @param float $alpha criterion value - * @return int + * @param float $trials number of Bernoulli trials + * @param float $probability probability of a success on each trial + * @param float $alpha criterion value + * @return int * * @todo Warning. This implementation differs from the algorithm detailed on the MS * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess @@ -3226,7 +3348,7 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } if ($alpha <= 0.5) { - $t = sqrt(log(1 / pow($alpha,2))); + $t = sqrt(log(1 / ($alpha * $alpha))); $trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t)); } else { $t = sqrt(log(1 / pow(1 - $alpha,2))); @@ -3302,13 +3424,13 @@ class PHPExcel_Calculation_Functions { /** - * CHIDIST + * CHIDIST * - * Returns the one-tailed probability of the chi-squared distribution. + * Returns the one-tailed probability of the chi-squared distribution. * - * @param float $value Value for the function - * @param float $degrees degrees of freedom - * @return float + * @param float $value Value for the function + * @param float $degrees degrees of freedom + * @return float */ public static function CHIDIST($value, $degrees) { $value = self::flattenSingleValue($value); @@ -3331,22 +3453,22 @@ class PHPExcel_Calculation_Functions { /** - * CHIINV + * CHIINV * - * Returns the one-tailed probability of the chi-squared distribution. + * Returns the one-tailed probability of the chi-squared distribution. * - * @param float $probability Probability for the function - * @param float $degrees degrees of freedom - * @return float + * @param float $probability Probability for the function + * @param float $degrees degrees of freedom + * @return float */ public static function CHIINV($probability, $degrees) { $probability = self::flattenSingleValue($probability); $degrees = floor(self::flattenSingleValue($degrees)); if ((is_numeric($probability)) && (is_numeric($degrees))) { + $xLo = 100; $xHi = 0; - $maxIteration = 100; $x = $xNew = 1; $dx = 1; @@ -3387,16 +3509,16 @@ class PHPExcel_Calculation_Functions { /** - * EXPONDIST + * EXPONDIST * - * Returns the exponential distribution. Use EXPONDIST to model the time between events, - * such as how long an automated bank teller takes to deliver cash. For example, you can - * use EXPONDIST to determine the probability that the process takes at most 1 minute. + * Returns the exponential distribution. Use EXPONDIST to model the time between events, + * such as how long an automated bank teller takes to deliver cash. For example, you can + * use EXPONDIST to determine the probability that the process takes at most 1 minute. * - * @param float $value Value of the function - * @param float $lambda The parameter value - * @param boolean $cumulative - * @return float + * @param float $value Value of the function + * @param float $lambda The parameter value + * @param boolean $cumulative + * @return float */ public static function EXPONDIST($value, $lambda, $cumulative) { $value = self::flattenSingleValue($value); @@ -3420,14 +3542,14 @@ class PHPExcel_Calculation_Functions { /** - * FISHER + * FISHER * - * Returns the Fisher transformation at x. This transformation produces a function that - * is normally distributed rather than skewed. Use this function to perform hypothesis - * testing on the correlation coefficient. + * Returns the Fisher transformation at x. This transformation produces a function that + * is normally distributed rather than skewed. Use this function to perform hypothesis + * testing on the correlation coefficient. * - * @param float $value - * @return float + * @param float $value + * @return float */ public static function FISHER($value) { $value = self::flattenSingleValue($value); @@ -3443,14 +3565,14 @@ class PHPExcel_Calculation_Functions { /** - * FISHERINV + * FISHERINV * - * Returns the inverse of the Fisher transformation. Use this transformation when - * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then - * FISHERINV(y) = x. + * Returns the inverse of the Fisher transformation. Use this transformation when + * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then + * FISHERINV(y) = x. * - * @param float $value - * @return float + * @param float $value + * @return float */ public static function FISHERINV($value) { $value = self::flattenSingleValue($value); @@ -3468,11 +3590,11 @@ class PHPExcel_Calculation_Functions { private static $_logBetaCache_result = 0.0; /** - * The natural logarithm of the beta function. - * @param p require p>0 - * @param q require q>0 - * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow - * @author Jaco van Kooten + * The natural logarithm of the beta function. + * @param p require p>0 + * @param q require q>0 + * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow + * @author Jaco van Kooten */ private static function _logBeta($p, $q) { if ($p != self::$_logBetaCache_p || $q != self::$_logBetaCache_q) { @@ -3489,9 +3611,9 @@ class PHPExcel_Calculation_Functions { /** - * Evaluates of continued fraction part of incomplete beta function. - * Based on an idea from Numerical Recipes (W.H. Press et al, 1992). - * @author Jaco van Kooten + * Evaluates of continued fraction part of incomplete beta function. + * Based on an idea from Numerical Recipes (W.H. Press et al, 1992). + * @author Jaco van Kooten */ private static function _betaFraction($x, $p, $q) { $c = 1.0; @@ -3859,7 +3981,6 @@ class PHPExcel_Calculation_Functions { } $a = 0; $b = 2; - $maxIteration = 100; $i = 0; while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) { @@ -3922,7 +4043,7 @@ class PHPExcel_Calculation_Functions { for ($j=1;$j<=6;++$j) { $summer += ($p[$j] / ++$y); } - return exp(0 - $tmp + log(2.5066282746310005 * $summer / $x)); + return exp(0 - $tmp + log(SQRT2PI * $summer / $x)); } // function _gamma() @@ -3967,7 +4088,6 @@ class PHPExcel_Calculation_Functions { * @param float $probability Probability at which you want to evaluate the distribution * @param float $alpha Parameter to the distribution * @param float $beta Parameter to the distribution - * @param boolean $cumulative * @return float * */ @@ -3975,41 +4095,38 @@ class PHPExcel_Calculation_Functions { $probability = self::flattenSingleValue($probability); $alpha = self::flattenSingleValue($alpha); $beta = self::flattenSingleValue($beta); -// $rMin = self::flattenSingleValue($rMin); -// $rMax = self::flattenSingleValue($rMax); if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) { - if (($alpha <= 0) || ($beta <= 0) || ($probability <= 0) || ($probability > 1)) { + if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) { return self::$_errorCodes['num']; } + $xLo = 0; - $xHi = 100; - $maxIteration = 100; + $xHi = $alpha * $beta * 5; $x = $xNew = 1; - $dx = 1; + $error = $pdf = 0; + $dx = 1024; $i = 0; while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { // Apply Newton-Raphson step - $result = self::GAMMADIST($x, $alpha, $beta, True); - $error = $result - $probability; - if ($error == 0.0) { - $dx = 0; - } elseif ($error < 0.0) { + $error = self::GAMMADIST($x, $alpha, $beta, True) - $probability; + if ($error < 0.0) { $xLo = $x; } else { $xHi = $x; } + $pdf = self::GAMMADIST($x, $alpha, $beta, False); // Avoid division by zero - if ($result != 0.0) { - $dx = $error / $result; + if ($pdf != 0.0) { + $dx = $error / $pdf; $xNew = $x - $dx; } // If the NR fails to converge (which for example may be the // case if the initial guess is too rough) we apply a bisection // step to determine a more narrow interval around the root. - if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { + if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) { $xNew = ($xLo + $xHi) / 2; $dx = $xNew - $x; } @@ -4018,7 +4135,7 @@ class PHPExcel_Calculation_Functions { if ($i == MAX_ITERATIONS) { return self::$_errorCodes['na']; } - return round($x,12); + return $x; } return self::$_errorCodes['value']; } // function GAMMAINV() @@ -4072,7 +4189,7 @@ class PHPExcel_Calculation_Functions { if ($cumulative) { return 0.5 * (1 + self::_erfVal(($value - $mean) / ($stdDev * sqrt(2)))); } else { - return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean,2) / (2 * pow($stdDev,2)))); + return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean,2) / (2 * ($stdDev * $stdDev)))); } } } @@ -4224,7 +4341,7 @@ class PHPExcel_Calculation_Functions { $y = $prob - 0.5; if (abs($y) < 0.42) { - $z = pow($y,2); + $z = ($y * $y); $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1); } else { if ($y > 0) { @@ -4475,8 +4592,6 @@ class PHPExcel_Calculation_Functions { // Laboratory as reported in (among other places) "Applied Statistics // Algorithms", editied by P Griffiths and I D Hill (1985; Ellis // Horwood Ltd.; W. Sussex, England). -// $ta = 2 / pi(); - $ta = 0.636619772367581; $tterm = $degrees; $ttheta = atan2($value,sqrt($tterm)); $tc = cos($ttheta); @@ -4498,7 +4613,7 @@ class PHPExcel_Calculation_Functions { $ti += 2; } $tsum *= $ts; - if (($degrees % 2) == 1) { $tsum = $ta * ($tsum + $ttheta); } + if (($degrees % 2) == 1) { $tsum = M_2DIVPI * ($tsum + $ttheta); } $tValue = 0.5 * (1 + $tsum); if ($tails == 1) { return 1 - abs($tValue); @@ -4526,7 +4641,6 @@ class PHPExcel_Calculation_Functions { if ((is_numeric($probability)) && (is_numeric($degrees))) { $xLo = 100; $xHi = 0; - $maxIteration = 100; $x = $xNew = 1; $dx = 1; @@ -4666,6 +4780,33 @@ class PHPExcel_Calculation_Functions { } // function WEIBULL() + /** + * ZTEST + * + * Returns the Weibull distribution. Use this distribution in reliability + * analysis, such as calculating a device's mean time to failure. + * + * @param float $value + * @param float $alpha Alpha Parameter + * @param float $beta Beta Parameter + * @param boolean $cumulative + * @return float + * + */ + public static function ZTEST($dataSet, $m0, $sigma=null) { + $dataSet = self::flattenArrayIndexed($dataSet); + $m0 = self::flattenSingleValue($m0); + $sigma = self::flattenSingleValue($sigma); + + if (is_null($sigma)) { + $sigma = self::STDEV($dataSet); + } + $n = count($dataSet); + + return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0)/($sigma/SQRT($n))); + } // function ZTEST() + + /** * SKEW * @@ -4678,17 +4819,21 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function SKEW() { - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $mean = self::AVERAGE($aArgs); $stdDev = self::STDEV($aArgs); $count = $summer = 0; // Loop through arguments - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summer += pow((($arg - $mean) / $stdDev),3) ; - ++$count; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summer += pow((($arg - $mean) / $stdDev),3) ; + ++$count; + } } } @@ -4712,18 +4857,22 @@ class PHPExcel_Calculation_Functions { * @return float */ public static function KURT() { - $aArgs = self::flattenArray(func_get_args()); + $aArgs = self::flattenArrayIndexed(func_get_args()); $mean = self::AVERAGE($aArgs); $stdDev = self::STDEV($aArgs); if ($stdDev > 0) { $count = $summer = 0; // Loop through arguments - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summer += pow((($arg - $mean) / $stdDev),4) ; - ++$count; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!self::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summer += pow((($arg - $mean) / $stdDev),4) ; + ++$count; + } } } @@ -4766,6 +4915,14 @@ class PHPExcel_Calculation_Functions { $a = self::flattenSingleValue($a); $b = self::flattenSingleValue($b); + if ($b == 0.0) { + return self::$_errorCodes['divisionbyzero']; + } elseif (($a < 0.0) && ($b > 0.0)) { + return $b - fmod(abs($a),$b); + } elseif (($a > 0.0) && ($b < 0.0)) { + return $b + fmod($a,abs($b)); + } + return fmod($a,$b); } // function MOD() @@ -4779,6 +4936,10 @@ class PHPExcel_Calculation_Functions { public static function CHARACTER($character) { $character = self::flattenSingleValue($character); + if ((!is_numeric($character)) || ($character < 0)) { + return self::$_errorCodes['value']; + } + if (function_exists('mb_convert_encoding')) { return mb_convert_encoding('&#'.intval($character).';', 'UTF-8', 'HTML-ENTITIES'); } else { @@ -4786,6 +4947,25 @@ class PHPExcel_Calculation_Functions { } } + + private static function _uniord($c) { + if (ord($c{0}) >=0 && ord($c{0}) <= 127) + return ord($c{0}); + if (ord($c{0}) >= 192 && ord($c{0}) <= 223) + return (ord($c{0})-192)*64 + (ord($c{1})-128); + if (ord($c{0}) >= 224 && ord($c{0}) <= 239) + return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); + if (ord($c{0}) >= 240 && ord($c{0}) <= 247) + return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); + if (ord($c{0}) >= 248 && ord($c{0}) <= 251) + return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); + if (ord($c{0}) >= 252 && ord($c{0}) <= 253) + return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); + if (ord($c{0}) >= 254 && ord($c{0}) <= 255) //error + return self::$_errorCodes['value']; + return 0; + } // function _uniord() + /** * ASCIICODE * @@ -4806,22 +4986,14 @@ class PHPExcel_Calculation_Functions { } } + $character = $characters; if ((function_exists('mb_strlen')) && (function_exists('mb_substr'))) { - if (mb_strlen($characters, 'UTF-8') > 0) { - $character = mb_substr($characters, 0, 1, 'UTF-8'); - $byteLength = strlen($character); - $xValue = 0; - for ($i = 0; $i < $byteLength; ++$i) { - $xValue = ($xValue * 256) + ord($character{$i}); - } - return $xValue; - } + if (mb_strlen($characters, 'UTF-8') > 1) { $character = mb_substr($characters, 0, 1, 'UTF-8'); } + return self::_uniord($character); } else { - if (strlen($characters) > 0) { - return ord(substr($characters, 0, 1)); - } + if (strlen($characters) > 0) { $character = substr($characters, 0, 1); } + return ord($character); } - return self::$_errorCodes['value']; } // function ASCIICODE() @@ -4834,7 +5006,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = ''; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); foreach ($aArgs as $arg) { if (is_bool($arg)) { @@ -4866,6 +5038,10 @@ class PHPExcel_Calculation_Functions { public static function STRINGLENGTH($value = '') { $value = self::flattenSingleValue($value); + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_strlen')) { return mb_strlen($value, 'UTF-8'); } else { @@ -4883,18 +5059,24 @@ class PHPExcel_Calculation_Functions { * @return string */ public static function SEARCHSENSITIVE($needle,$haystack,$offset=1) { - $needle = (string) self::flattenSingleValue($needle); - $haystack = (string) self::flattenSingleValue($haystack); + $needle = self::flattenSingleValue($needle); + $haystack = self::flattenSingleValue($haystack); $offset = self::flattenSingleValue($offset); - if (($offset > 0) && (strlen($haystack) > $offset)) { - if (function_exists('mb_strpos')) { - $pos = mb_strpos($haystack, $needle, --$offset,'UTF-8'); - } else { - $pos = strpos($haystack, $needle, --$offset); + if (!is_bool($needle)) { + if (is_bool($haystack)) { + $haystack = ($haystack) ? 'TRUE' : 'FALSE'; } - if ($pos !== false) { - return ++$pos; + + if (($offset > 0) && (strlen($haystack) > $offset)) { + if (function_exists('mb_strpos')) { + $pos = mb_strpos($haystack, $needle, --$offset,'UTF-8'); + } else { + $pos = strpos($haystack, $needle, --$offset); + } + if ($pos !== false) { + return ++$pos; + } } } return self::$_errorCodes['value']; @@ -4910,18 +5092,24 @@ class PHPExcel_Calculation_Functions { * @return string */ public static function SEARCHINSENSITIVE($needle,$haystack,$offset=1) { - $needle = (string) self::flattenSingleValue($needle); - $haystack = (string) self::flattenSingleValue($haystack); + $needle = self::flattenSingleValue($needle); + $haystack = self::flattenSingleValue($haystack); $offset = self::flattenSingleValue($offset); - if (($offset > 0) && (strlen($haystack) > $offset)) { - if (function_exists('mb_stripos')) { - $pos = mb_stripos($haystack, $needle, --$offset,'UTF-8'); - } else { - $pos = stripos($haystack, $needle, --$offset); + if (!is_bool($needle)) { + if (is_bool($haystack)) { + $haystack = ($haystack) ? 'TRUE' : 'FALSE'; } - if ($pos !== false) { - return ++$pos; + + if (($offset > 0) && (strlen($haystack) > $offset)) { + if (function_exists('mb_stripos')) { + $pos = mb_stripos($haystack, $needle, --$offset,'UTF-8'); + } else { + $pos = stripos($haystack, $needle, --$offset); + } + if ($pos !== false) { + return ++$pos; + } } } return self::$_errorCodes['value']; @@ -4939,6 +5127,14 @@ class PHPExcel_Calculation_Functions { $value = self::flattenSingleValue($value); $chars = self::flattenSingleValue($chars); + if ($chars < 0) { + return self::$_errorCodes['value']; + } + + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_substr')) { return mb_substr($value, 0, $chars, 'UTF-8'); } else { @@ -4958,6 +5154,14 @@ class PHPExcel_Calculation_Functions { $value = self::flattenSingleValue($value); $chars = self::flattenSingleValue($chars); + if ($chars < 0) { + return self::$_errorCodes['value']; + } + + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if ((function_exists('mb_substr')) && (function_exists('mb_strlen'))) { return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8'); } else { @@ -4979,6 +5183,14 @@ class PHPExcel_Calculation_Functions { $start = self::flattenSingleValue($start); $chars = self::flattenSingleValue($chars); + if (($start < 1) || ($chars < 0)) { + return self::$_errorCodes['value']; + } + + if (is_bool($value)) { + $value = ($value) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_substr')) { return mb_substr($value, --$start, $chars, 'UTF-8'); } else { @@ -5008,6 +5220,53 @@ class PHPExcel_Calculation_Functions { } // function REPLACE() + /** + * SUBSTITUTE + * + * @param string $text Value + * @param string $fromText From Value + * @param string $toText To Value + * @param integer $instance Instance Number + * @return string + */ + public static function SUBSTITUTE($text = '', $fromText = '', $toText = '', $instance = 0) { + $text = self::flattenSingleValue($text); + $fromText = self::flattenSingleValue($fromText); + $toText = self::flattenSingleValue($toText); + $instance = floor(self::flattenSingleValue($instance)); + + if ($instance == 0) { + if(function_exists('mb_str_replace')) { + return mb_str_replace($fromText,$toText,$text); + } else { + return str_replace($fromText,$toText,$text); + } + } else { + $pos = -1; + while($instance > 0) { + if (function_exists('mb_strpos')) { + $pos = mb_strpos($text, $fromText, $pos+1, 'UTF-8'); + } else { + $pos = strpos($text, $fromText, $pos+1); + } + if ($pos === false) { + break; + } + --$instance; + } + if ($pos !== false) { + if (function_exists('mb_strlen')) { + return self::REPLACE($text,++$pos,mb_strlen($fromText, 'UTF-8'),$toText); + } else { + return self::REPLACE($text,++$pos,strlen($fromText),$toText); + } + } + } + + return $left.$newText.$right; + } // function SUBSTITUTE() + + /** * RETURNSTRING * @@ -5055,6 +5314,10 @@ class PHPExcel_Calculation_Functions { $value = self::flattenSingleValue($value); $format = self::flattenSingleValue($format); + if ((is_string($value)) && (!is_numeric($value)) && PHPExcel_Shared_Date::isDateTimeFormatCode($format)) { + $value = self::DATEVALUE($value); + } + return (string) PHPExcel_Style_NumberFormat::toFormattedString($value,$format); } // function TEXTFORMAT() @@ -5086,6 +5349,10 @@ class PHPExcel_Calculation_Functions { public static function TRIMNONPRINTABLE($stringValue = '') { $stringValue = self::flattenSingleValue($stringValue); + if (is_bool($stringValue)) { + $stringValue = ($stringValue) ? 'TRUE' : 'FALSE'; + } + if (self::$_invalidChars == Null) { self::$_invalidChars = range(chr(0),chr(31)); } @@ -5123,7 +5390,7 @@ class PHPExcel_Calculation_Functions { * @param mixed $value Value to check * @return boolean */ - public static function IS_BLANK($value = null) { + public static function IS_BLANK($value=null) { if (!is_null($value)) { $value = self::flattenSingleValue($value); } @@ -5262,7 +5529,7 @@ class PHPExcel_Calculation_Functions { * @return string Version information */ public static function VERSION() { - return 'PHPExcel 1.7.0, 2009-08-10'; + return 'PHPExcel 1.7.2, 2010-01-11'; } // function VERSION() @@ -5408,7 +5675,7 @@ class PHPExcel_Calculation_Functions { * depending on the value of the ReturnDateType flag */ public static function DATEVALUE($dateValue = 1) { - $dateValue = str_replace(array('/','.',' '),array('-','-','-'),self::flattenSingleValue(trim($dateValue,'"'))); + $dateValue = str_replace(array('/','.',' '),array('-','-','-'),trim(self::flattenSingleValue($dateValue),'"')); $yearFound = false; $t1 = explode('-',$dateValue); @@ -5723,7 +5990,8 @@ class PHPExcel_Calculation_Functions { } break; case 'YM': - $retVal = abs(intval($endMonths - $startMonths)); + $retVal = intval($endMonths - $startMonths); + if ($retVal < 0) $retVal = 12 + $retVal; // We're only interested in full months if ($endDays < $startDays) { --$retVal; @@ -5736,7 +6004,8 @@ class PHPExcel_Calculation_Functions { $PHPEndDateObject->modify('-1 year'); $endYears = $PHPEndDateObject->format('Y'); } - $retVal = abs($PHPEndDateObject->format('z') - $PHPStartDateObject->format('z')); + $retVal = $PHPEndDateObject->format('z') - $PHPStartDateObject->format('z'); + if ($retVal < 0) { $retVal += 365; } } break; } @@ -5959,10 +6228,14 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue == 0.0) { + return 0; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function - $PHPDateObject = &PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); + $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); return (int) $PHPDateObject->format('j'); } // function DAYOFMONTH() @@ -5980,6 +6253,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6031,6 +6306,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6058,6 +6335,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6078,6 +6357,8 @@ class PHPExcel_Calculation_Functions { if (is_string($dateValue = self::_getDateValue($dateValue))) { return self::$_errorCodes['value']; + } elseif ($dateValue < 0.0) { + return self::$_errorCodes['num']; } // Execute function @@ -6109,15 +6390,14 @@ class PHPExcel_Calculation_Functions { } } // Execute function - if (is_real($timeValue)) { - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return self::$_errorCodes['num']; } - return (int) date('G',$timeValue); + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('G',$timeValue); } // function HOUROFDAY() @@ -6143,15 +6423,14 @@ class PHPExcel_Calculation_Functions { } } // Execute function - if (is_real($timeValue)) { - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return self::$_errorCodes['num']; } - return (int) date('i',$timeValue); + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('i',$timeValue); } // function MINUTEOFHOUR() @@ -6177,15 +6456,14 @@ class PHPExcel_Calculation_Functions { } } // Execute function - if (is_real($timeValue)) { - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return self::$_errorCodes['num']; } - return (int) date('s',$timeValue); + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('s',$timeValue); } // function SECONDOFMINUTE() @@ -6664,9 +6942,9 @@ class PHPExcel_Calculation_Functions { if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { return self::$_errorCodes['num']; } - $binVal = decbin(octdec($x)); + $r = decbin(octdec($x)); - return self::_nbrConversionFormat($binVal,$places); + return self::_nbrConversionFormat($r,$places); } // function OCTTOBIN() @@ -6892,16 +7170,16 @@ class PHPExcel_Calculation_Functions { if ($parsedComplex['imaginary'] == 0.0) { return 0.0; } elseif($parsedComplex['imaginary'] < 0.0) { - return pi() / -2; + return M_PI / -2; } else { - return pi() / 2; + return M_PI / 2; } } elseif ($parsedComplex['real'] > 0.0) { return atan($parsedComplex['imaginary'] / $parsedComplex['real']); } elseif ($parsedComplex['imaginary'] < 0.0) { - return 0 - (pi() - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real']))); + return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real']))); } else { - return pi() - atan($parsedComplex['imaginary'] / abs($parsedComplex['real'])); + return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real'])); } } // function IMARGUMENT() @@ -8106,7 +8384,7 @@ class PHPExcel_Calculation_Functions { $fTerm = pow($x / 2, $n) / self::FACT($n); $nK = 1; $fResult = $fTerm; - $fSqrX = pow($x,2) / 4; + $fSqrX = ($x * $x) / 4; do { $fTerm *= $fSqrX; $fTerm /= ($nK * ($nK + $n)); @@ -8142,16 +8420,15 @@ class PHPExcel_Calculation_Functions { if ($n < 0) { return self::$_errorCodes['num']; } - $f_2_DIV_PI = 2 / pi(); - $f_PI_DIV_2 = pi() / 2; - $f_PI_DIV_4 = pi() / 4; + $f_PI_DIV_2 = M_PI / 2; + $f_PI_DIV_4 = M_PI / 4; $fResult = 0; if (abs($x) <= 30) { $fTerm = pow($x / 2, $n) / self::FACT($n); $nK = 1; $fResult = $fTerm; - $fSqrX = pow($x,2) / -4; + $fSqrX = ($x * $x) / -4; do { $fTerm *= $fSqrX; $fTerm /= ($nK * ($nK + $n)); @@ -8159,7 +8436,7 @@ class PHPExcel_Calculation_Functions { } while ((abs($fTerm) > 1e-10) && (++$nK < 100)); } else { $fXAbs = abs($x); - $fResult = sqrt($f_2_DIV_PI / $fXAbs) * cos($fXAbs - $n * $f_PI_DIV_2 - $f_PI_DIV_4); + $fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $n * $f_PI_DIV_2 - $f_PI_DIV_4); if (($n && 1) && ($x < 0)) { $fResult = -$fResult; } @@ -8173,7 +8450,7 @@ class PHPExcel_Calculation_Functions { private static function _Besselk0($fNum) { if ($fNum <= 2) { $fNum2 = $fNum * 0.5; - $y = pow($fNum2,2); + $y = ($fNum2 * $fNum2); $fRet = -log($fNum2) * self::BESSELI($fNum, 0) + (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y * (0.10750e-3 + $y * 0.74e-5)))))); @@ -8190,7 +8467,7 @@ class PHPExcel_Calculation_Functions { private static function _Besselk1($fNum) { if ($fNum <= 2) { $fNum2 = $fNum * 0.5; - $y = pow($fNum2,2); + $y = ($fNum2 * $fNum2); $fRet = log($fNum2) * self::BESSELI($fNum, 1) + (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y * (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum; @@ -8244,17 +8521,17 @@ class PHPExcel_Calculation_Functions { private static function _Bessely0($fNum) { if ($fNum < 8.0) { - $y = pow($fNum,2); + $y = ($fNum * $fNum); $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733)))); $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y)))); - $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum); + $fRet = $f1 / $f2 + M_2DIVPI * self::BESSELJ($fNum, 0) * log($fNum); } else { $z = 8.0 / $fNum; - $y = pow($z,2); + $y = ($z * $z); $xx = $fNum - 0.785398164; $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6))); $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7)))); - $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); + $fRet = sqrt(M_2DIVPI / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); } return $fRet; } // function _Bessely0() @@ -8262,21 +8539,21 @@ class PHPExcel_Calculation_Functions { private static function _Bessely1($fNum) { if ($fNum < 8.0) { - $y = pow($fNum,2); + $y = ($fNum * $fNum); $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y * (-0.4237922726e7 + $y * 0.8511937935e4))))); $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y * (0.1020426050e6 + $y * (0.3549632885e3 + $y))))); - $fRet = $f1 / $f2 + 0.636619772 * ( self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum); + $fRet = $f1 / $f2 + M_2DIVPI * ( self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum); } else { $z = 8.0 / $fNum; - $y = pow($z,2); + $y = ($z * $z); $xx = $fNum - 2.356194491; $f1 = 1 + $y * (0.183105e-2 + $y * (-0.3516396496e-4 + $y * (0.2457520174e-5 + $y * (-0.240337019e6)))); $f2 = 0.04687499995 + $y * (-0.2002690873e-3 + $y * (0.8449199096e-5 + $y * (-0.88228987e-6 + $y * 0.105787412e-6))); - $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); + $fRet = sqrt(M_2DIVPI / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); #i12430# ...but this seems to work much better. -// $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491); +// $fRet = sqrt(M_2DIVPI / $fNum) * sin($fNum - 2.356194491); } return $fRet; } // function _Bessely1() @@ -8358,14 +8635,13 @@ class PHPExcel_Calculation_Functions { // Private method to calculate the erf value // private static $_two_sqrtpi = 1.128379167095512574; - private static $_rel_error = 1E-15; private static function _erfVal($x) { if (abs($x) > 2.2) { return 1 - self::_erfcVal($x); } $sum = $term = $x; - $xsqr = pow($x,2); + $xsqr = ($x * $x); $j = 1; do { $term *= $xsqr / $j; @@ -8374,10 +8650,10 @@ class PHPExcel_Calculation_Functions { $term *= $xsqr / $j; $sum += $term / (2 * $j + 1); ++$j; - if ($sum == 0) { + if ($sum == 0.0) { break; } - } while (abs($term / $sum) > self::$_rel_error); + } while (abs($term / $sum) > PRECISION); return self::$_two_sqrtpi * $sum; } // function _erfVal() @@ -8428,7 +8704,7 @@ class PHPExcel_Calculation_Functions { } $a = $n = 1; $b = $c = $x; - $d = pow($x,2) + 0.5; + $d = ($x * $x) + 0.5; $q1 = $q2 = $b / $d; $t = 0; do { @@ -8441,7 +8717,7 @@ class PHPExcel_Calculation_Functions { $n += 0.5; $q1 = $q2; $q2 = $b / $d; - } while ((abs($q1 - $q2) / $q2) > self::$_rel_error); + } while ((abs($q1 - $q2) / $q2) > PRECISION); return self::$_one_sqrtpi * exp(-$x * $x) * $q2; } // function _erfcVal() @@ -8478,6 +8754,10 @@ class PHPExcel_Calculation_Functions { public static function LOWERCASE($mixedCaseString) { $mixedCaseString = self::flattenSingleValue($mixedCaseString); + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_convert_case')) { return mb_convert_case($mixedCaseString, MB_CASE_LOWER, 'UTF-8'); } else { @@ -8497,6 +8777,10 @@ class PHPExcel_Calculation_Functions { public static function UPPERCASE($mixedCaseString) { $mixedCaseString = self::flattenSingleValue($mixedCaseString); + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_convert_case')) { return mb_convert_case($mixedCaseString, MB_CASE_UPPER, 'UTF-8'); } else { @@ -8516,6 +8800,10 @@ class PHPExcel_Calculation_Functions { public static function PROPERCASE($mixedCaseString) { $mixedCaseString = self::flattenSingleValue($mixedCaseString); + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; + } + if (function_exists('mb_convert_case')) { return mb_convert_case($mixedCaseString, MB_CASE_TITLE, 'UTF-8'); } else { @@ -8538,7 +8826,7 @@ class PHPExcel_Calculation_Functions { */ public static function DOLLAR($value = 0, $decimals = 2) { $value = self::flattenSingleValue($value); - $decimals = self::flattenSingleValue($decimals); + $decimals = is_null($decimals) ? 0 : self::flattenSingleValue($decimals); // Validate parameters if (!is_numeric($value) || !is_numeric($decimals)) { @@ -8730,6 +9018,22 @@ class PHPExcel_Calculation_Functions { } // function FV() + /** + * FVSCHEDULE + * + */ + public static function FVSCHEDULE($principal, $schedule) { + $principal = self::flattenSingleValue($principal); + $schedule = self::flattenArray($schedule); + + foreach($schedule as $n) { + $principal *= 1 + $n; + } + + return $principal; + } // function FVSCHEDULE() + + /** * PMT * @@ -8802,6 +9106,7 @@ class PHPExcel_Calculation_Functions { } // function NPER() + private static function _interestAndPrincipal($rate=0, $per=0, $nper=0, $pv=0, $fv=0, $type=0) { $pmt = self::PMT($rate, $nper, $pv, $fv, $type); $capital = $pv; @@ -8964,6 +9269,47 @@ class PHPExcel_Calculation_Functions { } // function CUMPRINC() + /** + * ISPMT + * + * Returns the interest payment for an investment based on an interest rate and a constant payment schedule. + * + * Excel Function: + * =ISPMT(interest_rate, period, number_payments, PV) + * + * interest_rate is the interest rate for the investment + * + * period is the period to calculate the interest rate. It must be betweeen 1 and number_payments. + * + * number_payments is the number of payments for the annuity + * + * PV is the loan amount or present value of the payments + */ + public static function ISPMT() { + // Return value + $returnValue = 0; + + // Get the parameters + $aArgs = self::flattenArray(func_get_args()); + $interestRate = array_shift($aArgs); + $period = array_shift($aArgs); + $numberPeriods = array_shift($aArgs); + $principleRemaining = array_shift($aArgs); + + // Calculate + $principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0); + for($i=0; $i <= $period; ++$i) { + $returnValue = $interestRate * $principleRemaining * -1; + $principleRemaining -= $principlePayment; + // principle needs to be 0 after the last payment, don't let floating point screw it up + if($i == $numberPeriods) { + $returnValue = 0; + } + } + return($returnValue); + } // function ISPMT() + + /** * NPV * @@ -8977,7 +9323,7 @@ class PHPExcel_Calculation_Functions { // Return value $returnValue = 0; - // Loop trough arguments + // Loop through arguments $aArgs = self::flattenArray(func_get_args()); // Calculate @@ -8994,6 +9340,188 @@ class PHPExcel_Calculation_Functions { } // function NPV() + /** + * XNPV + * + * Returns the net present value for a schedule of cash flows that is not necessarily periodic. + * To calculate the net present value for a series of cash flows that is periodic, use the NPV function. + * + * @param float Discount interest rate + * @param array Cash flow series + * @return float + */ + public static function XNPV($rate, $values, $dates) { + if ((!is_array($values)) || (!is_array($dates))) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $dates = self::flattenArray($dates); + $valCount = count($values); + if ($valCount != count($dates)) return self::$_errorCodes['num']; + + $xnpv = 0.0; + for ($i = 0; $i < $valCount; ++$i) { + $xnpv += $values[$i] / pow(1 + $rate, self::DATEDIF($dates[0],$dates[$i],'d') / 365); + } + return (is_finite($xnpv) ? $xnpv : self::$_errorCodes['value']); + } // function XNPV() + + + public static function IRR($values, $guess = 0.1) { + if (!is_array($values)) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $guess = self::flattenSingleValue($guess); + + // create an initial range, with a root somewhere between 0 and guess + $x1 = 0.0; + $x2 = $guess; + $f1 = self::NPV($x1, $values); + $f2 = self::NPV($x2, $values); + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + if (($f1 * $f2) < 0.0) break; + if (abs($f1) < abs($f2)) { + $f1 = self::NPV($x1 += 1.6 * ($x1 - $x2), $values); + } else { + $f2 = self::NPV($x2 += 1.6 * ($x2 - $x1), $values); + } + } + if (($f1 * $f2) > 0.0) return self::$_errorCodes['value']; + + $f = self::NPV($x1, $values); + if ($f < 0.0) { + $rtb = $x1; + $dx = $x2 - $x1; + } else { + $rtb = $x2; + $dx = $x1 - $x2; + } + + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + $dx *= 0.5; + $x_mid = $rtb + $dx; + $f_mid = self::NPV($x_mid, $values); + if ($f_mid <= 0.0) $rtb = $x_mid; + if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; + } + return self::$_errorCodes['value']; + } // function IRR() + + + public static function MIRR($values, $finance_rate, $reinvestment_rate) { + if (!is_array($values)) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $finance_rate = self::flattenSingleValue($finance_rate); + $reinvestment_rate = self::flattenSingleValue($reinvestment_rate); + $n = count($values); + + $rr = 1.0 + $reinvestment_rate; + $fr = 1.0 + $finance_rate; + + $npv_pos = $npv_neg = 0.0; + foreach($values as $i => $v) { + if ($v >= 0) { + $npv_pos += $v / pow($rr, $i); + } else { + $npv_neg += $v / pow($fr, $i); + } + } + + if (($npv_neg == 0) || ($npv_pos == 0) || ($reinvestment_rate <= -1)) { + return self::$_errorCodes['value']; + } + + $mirr = pow((-$npv_pos * pow($rr, $n)) + / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0; + + return (is_finite($mirr) ? $mirr : self::$_errorCodes['value']); + } // function MIRR() + + + public static function XIRR($values, $dates, $guess = 0.1) { + if ((!is_array($values)) && (!is_array($dates))) return self::$_errorCodes['value']; + $values = self::flattenArray($values); + $dates = self::flattenArray($dates); + $guess = self::flattenSingleValue($guess); + if (count($values) != count($dates)) return self::$_errorCodes['num']; + + // create an initial range, with a root somewhere between 0 and guess + $x1 = 0.0; + $x2 = $guess; + $f1 = self::XNPV($x1, $values, $dates); + $f2 = self::XNPV($x2, $values, $dates); + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + if (($f1 * $f2) < 0.0) break; + if (abs($f1) < abs($f2)) { + $f1 = self::XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates); + } else { + $f2 = self::XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates); + } + } + if (($f1 * $f2) > 0.0) return self::$_errorCodes['value']; + + $f = self::XNPV($x1, $values, $dates); + if ($f < 0.0) { + $rtb = $x1; + $dx = $x2 - $x1; + } else { + $rtb = $x2; + $dx = $x1 - $x2; + } + + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + $dx *= 0.5; + $x_mid = $rtb + $dx; + $f_mid = self::XNPV($x_mid, $values, $dates); + if ($f_mid <= 0.0) $rtb = $x_mid; + if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; + } + return self::$_errorCodes['value']; + } + + + /** + * RATE + * + **/ + public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { + $nper = (int) self::flattenSingleValue($nper); + $pmt = self::flattenSingleValue($pmt); + $pv = self::flattenSingleValue($pv); + $fv = (is_null($fv)) ? 0.0 : self::flattenSingleValue($fv); + $type = (is_null($type)) ? 0 : (int) self::flattenSingleValue($type); + $guess = (is_null($guess)) ? 0.1 : self::flattenSingleValue($guess); + + $rate = $guess; + if (abs($rate) < FINANCIAL_PRECISION) { + $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; + } else { + $f = exp($nper * log(1 + $rate)); + $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + } + $y0 = $pv + $pmt * $nper + $fv; + $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + + // find root by secant method + $i = $x0 = 0.0; + $x1 = $rate; + while ((abs($y0 - $y1) > FINANCIAL_PRECISION) && ($i < FINANCIAL_MAX_ITERATIONS)) { + $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0); + $x0 = $x1; + $x1 = $rate; + + if (abs($rate) < FINANCIAL_PRECISION) { + $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; + } else { + $f = exp($nper * log(1 + $rate)); + $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + } + + $y0 = $y1; + $y1 = $y; + ++$i; + } + return $rate; + } // function RATE() + + /** * DB * @@ -9039,6 +9567,9 @@ class PHPExcel_Calculation_Functions { } $previousDepreciation += $depreciation; } + if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { + $depreciation = round($depreciation,2); + } return $depreciation; } return self::$_errorCodes['value']; @@ -9080,6 +9611,9 @@ class PHPExcel_Calculation_Functions { $depreciation = min( ($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation) ); $previousDepreciation += $depreciation; } + if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { + $depreciation = round($depreciation,2); + } return $depreciation; } return self::$_errorCodes['value']; @@ -9133,9 +9667,9 @@ class PHPExcel_Calculation_Functions { $firstinter = self::flattenSingleValue($firstinter); $settlement = self::flattenSingleValue($settlement); $rate = (float) self::flattenSingleValue($rate); - $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); - $frequency = (is_null($frequency)) ? 1 : (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); + $frequency = (is_null($frequency)) ? 1 : (int) self::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); // Validate if ((is_numeric($rate)) && (is_numeric($par))) { @@ -9179,8 +9713,8 @@ class PHPExcel_Calculation_Functions { $issue = self::flattenSingleValue($issue); $settlement = self::flattenSingleValue($settlement); $rate = (float) self::flattenSingleValue($rate); - $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); + $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); + $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); // Validate if ((is_numeric($rate)) && (is_numeric($par))) { @@ -9204,13 +9738,116 @@ class PHPExcel_Calculation_Functions { public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { + $cost = self::flattenSingleValue($cost); + $purchased = self::flattenSingleValue($purchased); + $firstPeriod = self::flattenSingleValue($firstPeriod); + $salvage = self::flattenSingleValue($salvage); + $period = floor(self::flattenSingleValue($period)); + $rate = self::flattenSingleValue($rate); + $basis = floor(self::flattenSingleValue($basis)); + + $fUsePer = 1.0 / $rate; + + if ($fUsePer < 3.0) { + $amortiseCoeff = 1.0; + } elseif ($fUsePer < 5.0) { + $amortiseCoeff = 1.5; + } elseif ($fUsePer <= 6.0) { + $amortiseCoeff = 2.0; + } else { + $amortiseCoeff = 2.5; + } + + $rate *= $amortiseCoeff; + $fNRate = floor((self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost) + 0.5); + $cost -= $fNRate; + $fRest = $cost - $salvage; + + for ($n = 0; $n < $period; ++$n) { + $fNRate = floor(($rate * $cost) + 0.5); + $fRest -= $fNRate; + + if ($fRest < 0.0) { + switch ($period - $n) { + case 0 : + case 1 : return floor(($cost * 0.5) + 0.5); + break; + default : return 0.0; + break; + } + } + $cost -= $fNRate; + } + return $fNRate; } // function AMORDEGRC() public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { + $cost = self::flattenSingleValue($cost); + $purchased = self::flattenSingleValue($purchased); + $firstPeriod = self::flattenSingleValue($firstPeriod); + $salvage = self::flattenSingleValue($salvage); + $period = self::flattenSingleValue($period); + $rate = self::flattenSingleValue($rate); + $basis = self::flattenSingleValue($basis); + + $fOneRate = $cost * $rate; + $fCostDelta = $cost - $salvage; + $f0Rate = self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost; + $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate); + + if ($period == 0) { + return $f0Rate; + } elseif ($period <= $nNumOfFullPeriods) { + return $fOneRate; + } elseif ($period == ($nNumOfFullPeriods + 1)) { + return ($fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate); + } else { + return 0.0; + } } // function AMORLINC() + public static function COUPNUM($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = self::flattenSingleValue($frequency); + $basis = self::flattenSingleValue($basis); + + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis) * 365; + + switch ($frequency) { + case 1: // annual payments + return ceil($daysBetweenSettlementAndMaturity / 360); + case 2: // half-yearly + return ceil($daysBetweenSettlementAndMaturity / 180); + case 4: // quarterly + return ceil($daysBetweenSettlementAndMaturity / 90); + } + return self::$_errorCodes['value']; + } // function COUPNUM() + + + public static function COUPDAYBS($settlement, $maturity, $frequency, $basis=0) { + $settlement = self::flattenSingleValue($settlement); + $maturity = self::flattenSingleValue($maturity); + $frequency = self::flattenSingleValue($frequency); + $basis = self::flattenSingleValue($basis); + + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis) * 365; + + switch ($frequency) { + case 1: // annual payments + return 365 - ($daysBetweenSettlementAndMaturity % 360); + case 2: // half-yearly + return 365 - ($daysBetweenSettlementAndMaturity % 360); + case 4: // quarterly + return self::DATEDIF($maturity, $settlement); + } + return self::$_errorCodes['value']; + } // function COUPDAYBS() + + /** * DISC * @@ -9466,12 +10103,15 @@ class PHPExcel_Calculation_Functions { if (is_string($maturity = self::_getDateValue($maturity))) { return self::$_errorCodes['value']; } - ++$maturity; - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity); - $daysBetweenSettlementAndMaturity *= 360; + if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; + } else { + $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); + } - return (365 * $discount) / (360 - ($discount * ($daysBetweenSettlementAndMaturity))); + return (365 * $discount) / (360 - $discount * $daysBetweenSettlementAndMaturity); } // function TBILLEQ() @@ -9495,7 +10135,6 @@ class PHPExcel_Calculation_Functions { if (is_string($maturity = self::_getDateValue($maturity))) { return self::$_errorCodes['value']; } - ++$maturity; // Validate if (is_numeric($discount)) { @@ -9503,11 +10142,16 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; + if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + return $daysBetweenSettlementAndMaturity; + } + } else { + $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); } - $daysBetweenSettlementAndMaturity *= 360; + if ($daysBetweenSettlementAndMaturity > 360) { return self::$_errorCodes['num']; } @@ -9545,14 +10189,16 @@ class PHPExcel_Calculation_Functions { return self::$_errorCodes['num']; } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; + if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + return $daysBetweenSettlementAndMaturity; + } + } else { + $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); } - $daysBetweenSettlementAndMaturity *= 360; -// Sometimes we need to add 1, sometimes not. I haven't yet worked out the rule which determines this. - ++$daysBetweenSettlementAndMaturity; if ($daysBetweenSettlementAndMaturity > 360) { return self::$_errorCodes['num']; } @@ -9698,15 +10344,22 @@ class PHPExcel_Calculation_Functions { /** - * CELL_ADDRESS + * CELL_ADDRESS * - * Returns the straight-line depreciation of an asset for one period + * Creates a cell address as text, given specified row and column numbers. * - * @param row Row number to use in the cell reference - * @param column Column number to use in the cell reference - * @param relativity Flag indicating the type of reference to return - * @param sheetText Name of worksheet to use - * @return string + * @param row Row number to use in the cell reference + * @param column Column number to use in the cell reference + * @param relativity Flag indicating the type of reference to return + * 1 or omitted Absolute + * 2 Absolute row; relative column + * 3 Relative row; absolute column + * 4 Relative + * @param referenceStyle A logical value that specifies the A1 or R1C1 reference style. + * TRUE or omitted CELL_ADDRESS returns an A1-style reference + * FALSE CELL_ADDRESS returns an R1C1-style reference + * @param sheetText Optional Name of worksheet to use + * @return string */ public static function CELL_ADDRESS($row, $column, $relativity=1, $referenceStyle=True, $sheetText='') { $row = self::flattenSingleValue($row); @@ -9714,6 +10367,10 @@ class PHPExcel_Calculation_Functions { $relativity = self::flattenSingleValue($relativity); $sheetText = self::flattenSingleValue($sheetText); + if (($row < 1) || ($column < 1)) { + return self::$_errorCodes['value']; + } + if ($sheetText > '') { if (strpos($sheetText,' ') !== False) { $sheetText = "'".$sheetText."'"; } $sheetText .='!'; @@ -9732,85 +10389,268 @@ class PHPExcel_Calculation_Functions { } // function CELL_ADDRESS() + /** + * COLUMN + * + * Returns the column number of the given cell reference + * If the cell reference is a range of cells, COLUMN returns the column numbers of each column in the reference as a horizontal array. + * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the + * reference of the cell in which the COLUMN function appears; otherwise this function returns 0. + * + * @param cellAddress A reference to a range of cells for which you want the column numbers + * @return integer or array of integer + */ public static function COLUMN($cellAddress=Null) { - if (is_null($cellAddress) || $cellAddress === '') { - return 0; - } + if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } - foreach($cellAddress as $columnKey => $value) { - return PHPExcel_Cell::columnIndexFromString($columnKey); + if (is_array($cellAddress)) { + foreach($cellAddress as $columnKey => $value) { + $columnKey = preg_replace('/[^a-z]/i','',$columnKey); + return (integer) PHPExcel_Cell::columnIndexFromString($columnKey); + } + } else { + if (strpos($cellAddress,'!') !== false) { + list($sheet,$cellAddress) = explode('!',$cellAddress); + } + if (strpos($cellAddress,':') !== false) { + list($startAddress,$endAddress) = explode(':',$cellAddress); + $startAddress = preg_replace('/[^a-z]/i','',$startAddress); + $endAddress = preg_replace('/[^a-z]/i','',$endAddress); + $returnValue = array(); + do { + $returnValue[] = (integer) PHPExcel_Cell::columnIndexFromString($startAddress); + } while ($startAddress++ != $endAddress); + return $returnValue; + } else { + $cellAddress = preg_replace('/[^a-z]/i','',$cellAddress); + return (integer) PHPExcel_Cell::columnIndexFromString($cellAddress); + } } } // function COLUMN() - public static function ROW($cellAddress=Null) { - if ($cellAddress === Null) { - return 0; + /** + * COLUMNS + * + * Returns the number of columns in an array or reference. + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns + * @return integer + */ + public static function COLUMNS($cellAddress=Null) { + if (is_null($cellAddress) || $cellAddress === '') { + return 1; + } elseif (!is_array($cellAddress)) { + return self::$_errorCodes['value']; } - foreach($cellAddress as $columnKey => $rowValue) { - foreach($rowValue as $rowKey => $cellValue) { - return $rowKey; + $isMatrix = (is_numeric(array_shift(array_keys($cellAddress)))); + list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); + + if ($isMatrix) { + return $rows; + } else { + return $columns; + } + } // function COLUMNS() + + + /** + * ROW + * + * Returns the row number of the given cell reference + * If the cell reference is a range of cells, ROW returns the row numbers of each row in the reference as a vertical array. + * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the + * reference of the cell in which the ROW function appears; otherwise this function returns 0. + * + * @param cellAddress A reference to a range of cells for which you want the row numbers + * @return integer or array of integer + */ + public static function ROW($cellAddress=Null) { + if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } + + if (is_array($cellAddress)) { + foreach($cellAddress as $columnKey => $rowValue) { + foreach($rowValue as $rowKey => $cellValue) { + return (integer) preg_replace('/[^0-9]/i','',$rowKey); + } + } + } else { + if (strpos($cellAddress,'!') !== false) { + list($sheet,$cellAddress) = explode('!',$cellAddress); + } + if (strpos($cellAddress,':') !== false) { + list($startAddress,$endAddress) = explode(':',$cellAddress); + $startAddress = preg_replace('/[^0-9]/','',$startAddress); + $endAddress = preg_replace('/[^0-9]/','',$endAddress); + $returnValue = array(); + do { + $returnValue[][] = (integer) $startAddress; + } while ($startAddress++ != $endAddress); + return $returnValue; + } else { + list($cellAddress) = explode(':',$cellAddress); + return (integer) preg_replace('/[^0-9]/','',$cellAddress); } } } // function ROW() + /** + * ROWS + * + * Returns the number of rows in an array or reference. + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows + * @return integer + */ + public static function ROWS($cellAddress=Null) { + if (is_null($cellAddress) || $cellAddress === '') { + return 1; + } elseif (!is_array($cellAddress)) { + return self::$_errorCodes['value']; + } + + $isMatrix = (is_numeric(array_shift(array_keys($cellAddress)))); + list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); + + if ($isMatrix) { + return $columns; + } else { + return $rows; + } + } // function ROWS() + + + /** + * INDIRECT + * + * Returns the number of rows in an array or reference. + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows + * @return integer + */ + public static function INDIRECT($cellAddress=Null, PHPExcel_Cell $pCell = null) { + $cellAddress = self::flattenSingleValue($cellAddress); + if (is_null($cellAddress) || $cellAddress === '') { + return self::REF(); + } + + $cellAddress1 = $cellAddress; + $cellAddress2 = NULL; + if (strpos($cellAddress,':') !== false) { + list($cellAddress1,$cellAddress2) = explode(':',$cellAddress); + } + + if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress1, $matches)) || + ((!is_null($cellAddress2)) && (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress2, $matches)))) { + return self::REF(); + } + + if (strpos($cellAddress,'!') !== false) { + list($sheetName,$cellAddress) = explode('!',$cellAddress); + $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + } else { + $pSheet = $pCell->getParent(); + } + + return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); + } // function INDIRECT() + + + /** + * OFFSET + * + * Returns a reference to a range that is a specified number of rows and columns from a cell or range of cells. + * The reference that is returned can be a single cell or a range of cells. You can specify the number of rows and + * the number of columns to be returned. + * + * @param cellAddress The reference from which you want to base the offset. Reference must refer to a cell or + * range of adjacent cells; otherwise, OFFSET returns the #VALUE! error value. + * @param rows The number of rows, up or down, that you want the upper-left cell to refer to. + * Using 5 as the rows argument specifies that the upper-left cell in the reference is + * five rows below reference. Rows can be positive (which means below the starting reference) + * or negative (which means above the starting reference). + * @param cols The number of columns, to the left or right, that you want the upper-left cell of the result + * to refer to. Using 5 as the cols argument specifies that the upper-left cell in the + * reference is five columns to the right of reference. Cols can be positive (which means + * to the right of the starting reference) or negative (which means to the left of the + * starting reference). + * @param height The height, in number of rows, that you want the returned reference to be. Height must be a positive number. + * @param width The width, in number of columns, that you want the returned reference to be. Width must be a positive number. + * @return string A reference to a cell or range of cells + */ public static function OFFSET($cellAddress=Null,$rows=0,$columns=0,$height=null,$width=null) { if ($cellAddress == Null) { return 0; } - foreach($cellAddress as $startColumnKey => $rowValue) { - $startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumnKey); - foreach($rowValue as $startRowKey => $cellValue) { - break 2; - } - } - - foreach($cellAddress as $endColumnKey => $rowValue) { - foreach($rowValue as $endRowKey => $cellValue) { - } - } - $endColumnIndex = PHPExcel_Cell::columnIndexFromString($endColumnKey); - - $startColumnIndex += --$columns; - $startRowKey += $rows; - - if ($width == null) { - $endColumnIndex += $columns -1; - } else { - $endColumnIndex = $startColumnIndex + $width; - } - if ($height == null) { - $endRowKey += $rows; - } else { - $endRowKey = $startRowKey + $height -1; - } - - if (($startColumnIndex < 0) || ($startRowKey <= 0)) { + $pCell = array_pop(func_get_args()); + if (!is_object($pCell)) { return self::$_errorCodes['reference']; } - $startColumnKey = PHPExcel_Cell::stringFromColumnIndex($startColumnIndex); - $endColumnKey = PHPExcel_Cell::stringFromColumnIndex($endColumnIndex); - - $startCell = $startColumnKey.$startRowKey; - $endCell = $endColumnKey.$endRowKey; - - if ($startCell == $endCell) { - return $startColumnKey.$startRowKey; - } else { - return $startColumnKey.$startRowKey.':'.$endColumnKey.$endRowKey; + $sheetName = null; + if (strpos($cellAddress,"!")) { + list($sheetName,$cellAddress) = explode("!",$cellAddress); } + if (strpos($cellAddress,":")) { + list($startCell,$endCell) = explode(":",$cellAddress); + } else { + $startCell = $endCell = $cellAddress; + } + list($startCellColumn,$startCellRow) = PHPExcel_Cell::coordinateFromString($startCell); + list($endCellColumn,$endCellRow) = PHPExcel_Cell::coordinateFromString($endCell); + + $startCellRow += $rows; + $startCellColumn = PHPExcel_Cell::columnIndexFromString($startCellColumn) - 1; + $startCellColumn += $columns; + + if (($startCellRow <= 0) || ($startCellColumn < 0)) { + return self::$_errorCodes['reference']; + } + $endCellColumn = PHPExcel_Cell::columnIndexFromString($endCellColumn) - 1; + if (($width != null) && (!is_object($width))) { + $endCellColumn = $startCellColumn + $width - 1; + } else { + $endCellColumn += $columns; + } + $startCellColumn = PHPExcel_Cell::stringFromColumnIndex($startCellColumn); + + if (($height != null) && (!is_object($height))) { + $endCellRow = $startCellRow + $height - 1; + } else { + $endCellRow += $rows; + } + + if (($endCellRow <= 0) || ($endCellColumn < 0)) { + return self::$_errorCodes['reference']; + } + $endCellColumn = PHPExcel_Cell::stringFromColumnIndex($endCellColumn); + + $cellAddress = $startCellColumn.$startCellRow; + if (($startCellColumn != $endCellColumn) || ($startCellRow != $endCellRow)) { + $cellAddress .= ':'.$endCellColumn.$endCellRow; + } + + if ($sheetName !== null) { + $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + } else { + $pSheet = $pCell->getParent(); + } + + return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); } // function OFFSET() public static function CHOOSE() { $chooseArgs = func_get_args(); - $chosenEntry = self::flattenSingleValue(array_shift($chooseArgs)); + $chosenEntry = self::flattenArray(array_shift($chooseArgs)); $entryCount = count($chooseArgs) - 1; + if(is_array($chosenEntry)) { + $chosenEntry = array_shift($chosenEntry); + } if ((is_numeric($chosenEntry)) && (!is_bool($chosenEntry))) { --$chosenEntry; } else { @@ -9830,12 +10670,14 @@ class PHPExcel_Calculation_Functions { /** - * MATCH - * The MATCH function searches for a specified item in a range of cells - * @param lookup_value The value that you want to match in lookup_array - * @param lookup_array The range of cells being searched - * @param match_type The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. - * @return integer the relative position of the found item + * MATCH + * + * The MATCH function searches for a specified item in a range of cells + * + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_array The range of cells being searched + * @param match_type The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. + * @return integer The relative position of the found item */ public static function MATCH($lookup_value, $lookup_array, $match_type=1) { @@ -9964,7 +10806,8 @@ class PHPExcel_Calculation_Functions { } $rowKeys = array_keys($arrayValues); - $columnKeys = array_keys($arrayValues[$rowKeys[0]]); + $columnKeys = @array_keys($arrayValues[$rowKeys[0]]); + if ($columnNum > count($columnKeys)) { return self::$_errorCodes['value']; } elseif ($columnNum == 0) { @@ -9974,7 +10817,15 @@ class PHPExcel_Calculation_Functions { $rowNum = $rowKeys[--$rowNum]; $returnArray = array(); foreach($arrayValues as $arrayColumn) { - $returnArray[] = $arrayColumn[$rowNum]; + if (is_array($arrayColumn)) { + if (isset($arrayColumn[$rowNum])) { + $returnArray[] = $arrayColumn[$rowNum]; + } else { + return $arrayValues[$rowNum]; + } + } else { + return $arrayValues[$rowNum]; + } } return $returnArray; } @@ -10009,7 +10860,7 @@ class PHPExcel_Calculation_Functions { // Calculate if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period))) { - if (($life < 1) || ($salvage < $life) || ($period > $life)) { + if (($life < 1) || ($period > $life)) { return self::$_errorCodes['num']; } return (($cost - $salvage) * ($life - $period + 1) * 2) / ($life * ($life + 1)); @@ -10034,7 +10885,7 @@ class PHPExcel_Calculation_Functions { foreach($matrixData as $matrixRow) { $row = 0; foreach($matrixRow as $matrixCell) { - $returnMatrix[$column][$row] = $matrixCell; + $returnMatrix[$row][$column] = $matrixCell; ++$row; } ++$column; @@ -10162,6 +11013,37 @@ class PHPExcel_Calculation_Functions { } // function MDETERM() + /** + * SUMPRODUCT + * + * @param mixed $value Value to check + * @return float + */ + public static function SUMPRODUCT() { + $arrayList = func_get_args(); + + $wrkArray = self::flattenArray(array_shift($arrayList)); + $wrkCellCount = count($wrkArray); + + foreach($arrayList as $matrixData) { + $array2 = self::flattenArray($matrixData); + $count = count($array2); + if ($wrkCellCount != $count) { + return self::$_errorCodes['value']; + } + + foreach ($array2 as $i => $val) { + if (((is_numeric($wrkArray[$i])) && (!is_string($wrkArray[$i]))) && + ((is_numeric($val)) && (!is_string($val)))) { + $wrkArray[$i] *= $val; + } + } + } + + return array_sum($wrkArray); + } // function SUMPRODUCT() + + /** * SUMX2MY2 * @@ -10249,6 +11131,15 @@ class PHPExcel_Calculation_Functions { } // function SUMXMY2() + private static function _vlookupSort($a,$b) { + $firstColumn = array_shift(array_keys($a)); + if (strtolower($a[$firstColumn]) == strtolower($b[$firstColumn])) { + return 0; + } + return (strtolower($a[$firstColumn]) < strtolower($b[$firstColumn])) ? -1 : 1; + } // function _vlookupSort() + + /** * VLOOKUP * The VLOOKUP function searches for value in the left-most column of lookup_array and returns the value in the same row based on the index_number. @@ -10265,109 +11156,130 @@ class PHPExcel_Calculation_Functions { } // index_number must be less than or equal to the number of columns in lookup_array - if ($index_number > count($lookup_array)) { + if ((!is_array($lookup_array)) || (count($lookup_array) < 1)) { return self::$_errorCodes['reference']; - } - - // re-index lookup_array with numeric keys starting at 1 - array_unshift($lookup_array, array()); - $lookup_array = array_slice(array_values($lookup_array), 1, count($lookup_array), true); - - // look for an exact match - $row_number = array_search($lookup_value, $lookup_array[1]); - - // if an exact match is required, we have what we need to return an appropriate response - if ($not_exact_match == false) { - if ($row_number === false) { - return self::$_errorCodes['na']; + } else { + $firstRow = array_pop(array_keys($lookup_array)); + if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { + return self::$_errorCodes['reference']; } else { - return $lookup_array[$index_number][$row_number]; + $columnKeys = array_keys($lookup_array[$firstRow]); + $returnColumn = $columnKeys[--$index_number]; + $firstColumn = array_shift($columnKeys); + } + } + + if (!$not_exact_match) { + uasort($lookup_array,array('self','_vlookupSort')); + } + + $rowNumber = $rowValue = False; + foreach($lookup_array as $rowKey => $rowData) { + if (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)) { + break; + } + $rowNumber = $rowKey; + $rowValue = $rowData[$firstColumn]; + } + + if ($rowNumber !== false) { + if ((!$not_exact_match) && ($rowValue != $lookup_value)) { + // if an exact match is required, we have what we need to return an appropriate response + return self::$_errorCodes['na']; + } else { + // otherwise return the appropriate value + return $lookup_array[$rowNumber][$returnColumn]; } } - // TODO: The VLOOKUP spec in Excel states that, at this point, we should search for - // the highest value that is less than lookup_value. However, documentation on how string - // values should be treated here is sparse. return self::$_errorCodes['na']; } // function VLOOKUP() + /** - * LOOKUP - * The LOOKUP function searches for value either from a one-row or one-column range or from an array. - * @param lookup_value The value that you want to match in lookup_array - * @param lookup_vector The range of cells being searched - * @param result_vector The column from which the matching value must be returned - * @return mixed The value of the found cell - */ + * LOOKUP + * The LOOKUP function searches for value either from a one-row or one-column range or from an array. + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_vector The range of cells being searched + * @param result_vector The column from which the matching value must be returned + * @return mixed The value of the found cell + */ public static function LOOKUP($lookup_value, $lookup_vector, $result_vector=null) { + $lookup_value = self::flattenSingleValue($lookup_value); - // check for LOOKUP Syntax (view Excel documentation) - if( is_null($result_vector) ) - { - // TODO: Syntax 2 (array) - } else { - // Syntax 1 (vector) - // get key (column or row) of lookup_vector - $kl = key($lookup_vector); - // check if lookup_value exists in lookup_vector - if( in_array($lookup_value, $lookup_vector[$kl]) ) - { - // FOUND IT! Get key of lookup_vector - $k_res = array_search($lookup_value, $lookup_vector[$kl]); - } else { - // value NOT FOUND - // Get the smallest value in lookup_vector - // The LOOKUP spec in Excel states --> IMPORTANT - The values in lookup_vector must be placed in ascending order! - $ksv = key($lookup_vector[$kl]); - $smallest_value = $lookup_vector[$kl][$ksv]; - // If lookup_value is smaller than the smallest value in lookup_vector, LOOKUP gives the #N/A error value. - if( $lookup_value < $smallest_value ) - { - return self::$_errorCodes['na']; - } else { - // If LOOKUP can't find the lookup_value, it matches the largest value in lookup_vector that is less than or equal to lookup_value. - // IMPORTANT : In Excel Documentation is not clear what happen if lookup_value is text! - foreach( $lookup_vector[$kl] AS $kk => $value ) - { - if( $lookup_value >= $value ) - { - $k_res = $kk; - } - } - } - } - - // Returns a value from the same position in result_vector - // get key (column or row) of result_vector - $kr = key($result_vector); - if( isset($result_vector[$kr][$k_res]) ) - { - return $result_vector[$kr][$k_res]; - } else { - // TODO: In Excel Documentation is not clear what happen here... - } + if (!is_array($lookup_vector)) { + return self::$_errorCodes['na']; } + $lookupRows = count($lookup_vector); + $lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]); + if ((($lookupRows == 1) && ($lookupColumns > 1)) || (($lookupRows == 2) && ($lookupColumns != 2))) { + $lookup_vector = self::TRANSPOSE($lookup_vector); + $lookupRows = count($lookup_vector); + $lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]); + } + + if (is_null($result_vector)) { + $result_vector = $lookup_vector; + } + $resultRows = count($result_vector); + $resultColumns = count($result_vector[array_shift(array_keys($result_vector))]); + if ((($resultRows == 1) && ($resultColumns > 1)) || (($resultRows == 2) && ($resultColumns != 2))) { + $result_vector = self::TRANSPOSE($result_vector); + $resultRows = count($result_vector); + $resultColumns = count($result_vector[array_shift(array_keys($result_vector))]); + } + + if ($lookupRows == 2) { + $result_vector = array_pop($lookup_vector); + $lookup_vector = array_shift($lookup_vector); + } + if ($lookupColumns != 2) { + foreach($lookup_vector as &$value) { + if (is_array($value)) { + $key1 = $key2 = array_shift(array_keys($value)); + $key2++; + $dataValue1 = $value[$key1]; + } else { + $key1 = 0; + $key2 = 1; + $dataValue1 = $value; + } + $dataValue2 = array_shift($result_vector); + if (is_array($dataValue2)) { + $dataValue2 = array_shift($dataValue2); + } + $value = array($key1 => $dataValue1, $key2 => $dataValue2); + } + unset($value); + } + + return self::VLOOKUP($lookup_value,$lookup_vector,2); } // function LOOKUP() /** - * Flatten multidemensional array + * Convert a multi-dimensional array to a simple 1-dimensional array * - * @param array $array Array to be flattened - * @return array Flattened array + * @param array $array Array to be flattened + * @return array Flattened array */ public static function flattenArray($array) { - if(!is_array ( $array ) ){ - $array = array ( $array ); + if (!is_array($array)) { + return (array) $array; } $arrayValues = array(); - foreach ($array as $value) { - if (is_scalar($value)) { - $arrayValues[] = self::flattenSingleValue($value); - } elseif (is_array($value)) { - $arrayValues = array_merge($arrayValues, self::flattenArray($value)); + if (is_array($value)) { + foreach ($value as $val) { + if (is_array($val)) { + foreach ($val as $v) { + $arrayValues[] = $v; + } + } else { + $arrayValues[] = $val; + } + } } else { $arrayValues[] = $value; } @@ -10378,14 +11290,46 @@ class PHPExcel_Calculation_Functions { /** - * Convert an array with one element to a flat value + * Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing * - * @param mixed $value Array or flat value - * @return mixed + * @param array $array Array to be flattened + * @return array Flattened array + */ + public static function flattenArrayIndexed($array) { + if (!is_array($array)) { + return (array) $array; + } + + $arrayValues = array(); + foreach ($array as $k1 => $value) { + if (is_array($value)) { + foreach ($value as $k2 => $val) { + if (is_array($val)) { + foreach ($val as $k3 => $v) { + $arrayValues[$k1.'.'.$k2.'.'.$k3] = $v; + } + } else { + $arrayValues[$k1.'.'.$k2] = $val; + } + } + } else { + $arrayValues[$k1] = $value; + } + } + + return $arrayValues; + } // function flattenArrayIndexed() + + + /** + * Convert an array to a single scalar value by extracting the first element + * + * @param mixed $value Array or scalar value + * @return mixed */ public static function flattenSingleValue($value = '') { if (is_array($value)) { - $value = self::flattenSingleValue(array_pop($value)); + return self::flattenSingleValue(array_pop($value)); } return $value; } // function flattenSingleValue() @@ -10503,3 +11447,34 @@ if (!function_exists('money_format')) { return $format; } // function money_format() } + + +// +// Strangely, PHP doesn't have a mb_str_replace multibyte function +// As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set +// +if ((!function_exists('mb_str_replace')) && + (function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) { + function mb_str_replace($search, $replace, $subject) { + if(is_array($subject)) { + $ret = array(); + foreach($subject as $key => $val) { + $ret[$key] = mb_str_replace($search, $replace, $val); + } + return $ret; + } + + foreach((array) $search as $key => $s) { + if($s == '') { + continue; + } + $r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : ''); + $pos = mb_strpos($subject, $s, 0, 'UTF-8'); + while($pos !== false) { + $subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8'); + $pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8'); + } + } + return $subject; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Cell.php b/libraries/PHPExcel/PHPExcel/Cell.php index 9b321822a..c0603ac16 100644 --- a/libraries/PHPExcel/PHPExcel/Cell.php +++ b/libraries/PHPExcel/PHPExcel/Cell.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -64,7 +64,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell { @@ -136,11 +136,6 @@ class PHPExcel_Cell */ public function __construct($pColumn = 'A', $pRow = 1, $pValue = null, $pDataType = null, PHPExcel_Worksheet $pSheet = null) { - // Set value binder? - if (is_null(self::$_valueBinder)) { - self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder(); - } - // Initialise cell coordinate $this->_column = strtoupper($pColumn); $this->_row = $pRow; @@ -171,7 +166,7 @@ class PHPExcel_Cell */ public function getColumn() { - return strtoupper($this->_column); + return $this->_column; } /** @@ -226,22 +221,42 @@ class PHPExcel_Cell * @param mixed $pValue Value * @param string $pDataType Explicit data type * @return PHPExcel_Cell + * @throws Exception */ public function setValueExplicit($pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING) { - // check strings that they are ok - // TODO: fix also for RichText - if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING && !($pValue instanceof PHPExcel_RichText)) { - // string must never be longer than 32,767 characters, truncate if necessary - $pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); + // set the value according to data type + switch ($pDataType) { + case PHPExcel_Cell_DataType::TYPE_STRING: + case PHPExcel_Cell_DataType::TYPE_NULL: + case PHPExcel_Cell_DataType::TYPE_INLINE: + $this->_value = PHPExcel_Cell_DataType::checkString($pValue); + break; - // we require that newline is represented as "\n" in core, not as "\r\n" or "\r" - $pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); + case PHPExcel_Cell_DataType::TYPE_NUMERIC: + $this->_value = (float)$pValue; + break; + + case PHPExcel_Cell_DataType::TYPE_FORMULA: + $this->_value = (string)$pValue; + break; + + case PHPExcel_Cell_DataType::TYPE_BOOL: + $this->_value = (bool)$pValue; + break; + + case PHPExcel_Cell_DataType::TYPE_ERROR: + $this->_value = PHPExcel_Cell_DataType::checkErrorCode($pValue); + break; + + default: + throw new Exception('Invalid datatype: ' . $pDataType); + break; } - $this->_value = $pValue; - $this->_dataType = $pDataType; - return $this; + // set the datatype + $this->_dataType = $pDataType; + return $this; } /** @@ -492,22 +507,17 @@ class PHPExcel_Cell { if (strpos($pCoordinateString,':') !== false) { throw new Exception('Cell coordinate string can not be a range of cells.'); + } else if ($pCoordinateString == '') { throw new Exception('Cell coordinate can not be zero-length string.'); - } else { - // Column - $column = ''; - // Row - $row = ''; - - // Convert a cell reference - if (preg_match("/([$]?[A-Z]+)([$]?\d+)/", $pCoordinateString, $matches)) { - list(, $column, $row) = $matches; - } - - // Return array + } else if (preg_match("/([$]?[A-Z]+)([$]?\d+)/", $pCoordinateString, $matches)) { + list(, $column, $row) = $matches; return array($column, $row); + + } else { + throw new Exception('Invalid cell coordinate.'); + } } @@ -745,6 +755,10 @@ class PHPExcel_Cell * @return PHPExcel_Cell_IValueBinder */ public static function getValueBinder() { + if (is_null(self::$_valueBinder)) { + self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder(); + } + return self::$_valueBinder; } diff --git a/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php index f2c4019d3..d8e25645c 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/AdvancedValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder { @@ -124,21 +124,7 @@ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder return true; } } - - // Style logic - Numbers - if ($dataType === PHPExcel_Cell_DataType::TYPE_NUMERIC) { - // Leading zeroes? - if (preg_match('/^\-?[0]+[0-9]*\.?[0-9]*$/', $value)) { - // Convert value to string - $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_STRING); - - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_TEXT ); - - return true; - } - } - + // Not bound yet? Use parent... return parent::bindValue($cell, $value); } diff --git a/libraries/PHPExcel/PHPExcel/Cell/DataType.php b/libraries/PHPExcel/PHPExcel/Cell/DataType.php index cfe35765f..add1bec8b 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DataType.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DataType.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DefaultValueBinder.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DataType { @@ -82,4 +82,44 @@ class PHPExcel_Cell_DataType public static function dataTypeForValue($pValue = null) { return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue); } + + /** + * Check a string that it satisfies Excel requirements + * + * @param mixed Value to sanitize to an Excel string + * @return mixed Sanitized value + */ + public static function checkString($pValue = null) + { + if ($pValue instanceof PHPExcel_RichText) { + // TODO: Sanitize Rich-Text string (max. character count is 32,767) + return $pValue; + } + + // string must never be longer than 32,767 characters, truncate if necessary + $pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); + + // we require that newline is represented as "\n" in core, not as "\r\n" or "\r" + $pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); + + return $pValue; + } + + /** + * Check a value that it is a valid error code + * + * @param mixed Value to sanitize to an Excel error code + * @return string Sanitized value + */ + public static function checkErrorCode($pValue = null) + { + $pValue = (string)$pValue; + + if ( !array_key_exists($pValue, self::$_errorCodes) ) { + $pValue = '#NULL!'; + } + + return $pValue; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php b/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php index 234a93d6c..8d7f29329 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DataValidation.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DataValidation { diff --git a/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php index 29b0f6631..2b8bef72e 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/DefaultValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder { @@ -87,22 +87,31 @@ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder // Match the value against a few data types if (is_null($pValue)) { return PHPExcel_Cell_DataType::TYPE_NULL; + } elseif ($pValue === '') { return PHPExcel_Cell_DataType::TYPE_STRING; + } elseif ($pValue instanceof PHPExcel_RichText) { return PHPExcel_Cell_DataType::TYPE_STRING; + } elseif ($pValue{0} === '=') { return PHPExcel_Cell_DataType::TYPE_FORMULA; + } elseif (is_bool($pValue)) { return PHPExcel_Cell_DataType::TYPE_BOOL; + } elseif (is_float($pValue) || is_int($pValue)) { return PHPExcel_Cell_DataType::TYPE_NUMERIC; - } elseif (preg_match('/^\-?[0-9]*\\.?[0-9]*$/', $pValue)) { + + } elseif (preg_match('/^\-?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)$/', $pValue)) { return PHPExcel_Cell_DataType::TYPE_NUMERIC; + } elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) { return PHPExcel_Cell_DataType::TYPE_ERROR; + } else { return PHPExcel_Cell_DataType::TYPE_STRING; + } } } diff --git a/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php b/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php index 122424490..a4f3758f4 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php +++ b/libraries/PHPExcel/PHPExcel/Cell/Hyperlink.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_Hyperlink { diff --git a/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php b/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php index 479ed6920..3a4186ccf 100644 --- a/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php +++ b/libraries/PHPExcel/PHPExcel/Cell/IValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Cell_IValueBinder { diff --git a/libraries/PHPExcel/PHPExcel/Comment.php b/libraries/PHPExcel/PHPExcel/Comment.php index ea6cdb4b7..ee7254ac0 100644 --- a/libraries/PHPExcel/PHPExcel/Comment.php +++ b/libraries/PHPExcel/PHPExcel/Comment.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Comment implements PHPExcel_IComparable { @@ -290,37 +290,6 @@ class PHPExcel_Comment implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/DocumentProperties.php b/libraries/PHPExcel/PHPExcel/DocumentProperties.php index 609108dd1..41fe1fb7d 100644 --- a/libraries/PHPExcel/PHPExcel/DocumentProperties.php +++ b/libraries/PHPExcel/PHPExcel/DocumentProperties.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_DocumentProperties { diff --git a/libraries/PHPExcel/PHPExcel/DocumentSecurity.php b/libraries/PHPExcel/PHPExcel/DocumentSecurity.php index 65c64742f..6344d40e3 100644 --- a/libraries/PHPExcel/PHPExcel/DocumentSecurity.php +++ b/libraries/PHPExcel/PHPExcel/DocumentSecurity.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PasswordHasher.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_DocumentSecurity { diff --git a/libraries/PHPExcel/PHPExcel/HashTable.php b/libraries/PHPExcel/PHPExcel/HashTable.php index b516f7998..afbced953 100644 --- a/libraries/PHPExcel/PHPExcel/HashTable.php +++ b/libraries/PHPExcel/PHPExcel/HashTable.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_HashTable { @@ -101,26 +101,10 @@ class PHPExcel_HashTable * @throws Exception */ public function add(PHPExcel_IComparable $pSource = null) { - // Determine hashcode - $hashCode = null; - $hashIndex = $pSource->getHashIndex(); - if ( is_null ( $hashIndex ) ) { - $hashCode = $pSource->getHashCode(); - } else if ( isset ( $this->_keyMap[$hashIndex] ) ) { - $hashCode = $this->_keyMap[$hashIndex]; - } else { - $hashCode = $pSource->getHashCode(); - } - - // Add value - if (!isset($this->_items[ $hashCode ])) { - $this->_items[ $hashCode ] = $pSource; - $index = count($this->_items) - 1; - $this->_keyMap[ $index ] = $hashCode; - $pSource->setHashIndex( $index ); - } else { - $pSource->setHashIndex( $this->_items[ $hashCode ]->getHashIndex() ); - } + if (!isset($this->_items[ $pSource->getHashCode() ])) { + $this->_items[ $pSource->getHashCode() ] = $pSource; + $this->_keyMap[ count($this->_items) - 1 ] = $pSource->getHashCode(); + } } /** diff --git a/libraries/PHPExcel/PHPExcel/IComparable.php b/libraries/PHPExcel/PHPExcel/IComparable.php index f02271fca..1a3a689ea 100644 --- a/libraries/PHPExcel/PHPExcel/IComparable.php +++ b/libraries/PHPExcel/PHPExcel/IComparable.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -29,7 +29,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_IComparable { @@ -39,24 +39,5 @@ interface PHPExcel_IComparable * @return string Hash code */ public function getHashCode(); - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex(); - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value); + } diff --git a/libraries/PHPExcel/PHPExcel/IOFactory.php b/libraries/PHPExcel/PHPExcel/IOFactory.php index e3a623080..f116bc012 100644 --- a/libraries/PHPExcel/PHPExcel/IOFactory.php +++ b/libraries/PHPExcel/PHPExcel/IOFactory.php @@ -2,27 +2,27 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 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 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,10 +49,10 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReader.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_IOFactory -{ +{ /** * Search locations * @@ -62,24 +62,27 @@ class PHPExcel_IOFactory array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) ); - + /** * Autoresolve classes - * + * * @var array */ private static $_autoResolveClasses = array( 'Excel2007', 'Excel5', + 'Excel2003XML', + 'OOCalc', + 'SYLK', 'Serialized', - 'CSV' + 'CSV', ); - + /** * Private constructor for PHPExcel_IOFactory */ private function __construct() { } - + /** * Get search locations * @@ -88,10 +91,10 @@ class PHPExcel_IOFactory public static function getSearchLocations() { return self::$_searchLocations; } - + /** * Set search locations - * + * * @param array $value * @throws Exception */ @@ -102,10 +105,10 @@ class PHPExcel_IOFactory throw new Exception('Invalid parameter passed.'); } } - + /** * Add search location - * + * * @param string $type Example: IWriter * @param string $location Example: PHPExcel/Writer/{0}.php * @param string $classname Example: PHPExcel_Writer_{0} @@ -113,7 +116,7 @@ class PHPExcel_IOFactory public static function addSearchLocation($type = '', $location = '', $classname = '') { self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); } - + /** * Create PHPExcel_Writer_IWriter * @@ -124,28 +127,28 @@ class PHPExcel_IOFactory public static function createWriter(PHPExcel $phpExcel, $writerType = '') { // Search type $searchType = 'IWriter'; - + // Include class foreach (self::$_searchLocations as $searchLocation) { if ($searchLocation['type'] == $searchType) { $className = str_replace('{0}', $writerType, $searchLocation['class']); $classFile = str_replace('{0}', $writerType, $searchLocation['path']); - + if (!class_exists($className)) { require_once PHPEXCEL_ROOT . $classFile; } - + $instance = new $className($phpExcel); if (!is_null($instance)) { return $instance; } } } - + // Nothing found... throw new Exception("No $searchType found for type $writerType"); } - + /** * Create PHPExcel_Reader_IReader * @@ -155,34 +158,34 @@ class PHPExcel_IOFactory public static function createReader($readerType = '') { // Search type $searchType = 'IReader'; - + // Include class foreach (self::$_searchLocations as $searchLocation) { if ($searchLocation['type'] == $searchType) { $className = str_replace('{0}', $readerType, $searchLocation['class']); $classFile = str_replace('{0}', $readerType, $searchLocation['path']); - + if (!class_exists($className)) { require_once PHPEXCEL_ROOT . $classFile; } - + $instance = new $className(); if (!is_null($instance)) { return $instance; } } } - + // Nothing found... throw new Exception("No $searchType found for type $readerType"); } - + /** * Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution * * @param string $pFileName * @return PHPExcel - */ + */ public static function load($pFilename) { $reader = self::createReaderForFile($pFilename); return $reader->load($pFilename); @@ -193,9 +196,55 @@ class PHPExcel_IOFactory * * @param string $pFileName * @return PHPExcel_Reader_IReader - * @throws Exception - */ + */ public static function createReaderForFile($pFilename) { + + // First, lucky guess by inspecting file extension + $pathinfo = pathinfo($pFilename); + + if (isset($pathinfo['extension'])) { + + switch (strtolower($pathinfo['extension'])) { + case 'xlsx': + $reader = self::createReader('Excel2007'); + break; + + case 'xls': + $reader = self::createReader('Excel5'); + break; + + case 'ods': + $reader = self::createReader('OOCalc'); + break; + + case 'slk': + $reader = self::createReader('SYLK'); + break; + + case 'xml': + $reader = self::createReader('Excel2003XML'); + break; + + case 'csv': + // Do nothing + // We must not try to use CSV reader since it loads + // all files including Excel files etc. + break; + + default: + break; + + } + + // Let's see if we are lucky + if ($reader->canRead($pFilename)) { + return $reader; + } + + } + + // If we reach here then "lucky guess" didn't give any result + // Try loading using self::$_autoResolveClasses foreach (self::$_autoResolveClasses as $autoResolveClass) { $reader = self::createReader($autoResolveClass); @@ -204,6 +253,5 @@ class PHPExcel_IOFactory } } - throw new Exception("Could not automatically determine PHPExcel_Reader_IReader for file."); } } diff --git a/libraries/PHPExcel/PHPExcel/NamedRange.php b/libraries/PHPExcel/PHPExcel/NamedRange.php index ba6ad281e..87054a5f8 100644 --- a/libraries/PHPExcel/PHPExcel/NamedRange.php +++ b/libraries/PHPExcel/PHPExcel/NamedRange.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_NamedRange { diff --git a/libraries/PHPExcel/PHPExcel/Reader/CSV.php b/libraries/PHPExcel/PHPExcel/Reader/CSV.php index 30e894b6b..8758112fb 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/CSV.php +++ b/libraries/PHPExcel/PHPExcel/Reader/CSV.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,10 +55,17 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader { + /** + * Input encoding + * + * @var string + */ + private $_inputEncoding; + /** * Delimiter * @@ -98,6 +105,7 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader * Create a new PHPExcel_Reader_CSV */ public function __construct() { + $this->_inputEncoding = 'UTF-8'; $this->_delimiter = ','; $this->_enclosure = '"'; $this->_lineEnding = PHP_EOL; @@ -117,9 +125,8 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader if (!file_exists($pFilename)) { throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); } - - // Check if it is a CSV file (using file name) - return (substr(strtolower($pFilename), -3) == 'csv'); + + return true; } /** @@ -155,6 +162,26 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader $this->_readFilter = $pValue; } + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'UTF-8') + { + $this->_inputEncoding = $pValue; + } + + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } + /** * Loads PHPExcel from file into PHPExcel instance * @@ -181,7 +208,18 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader throw new Exception("Could not open file $pFilename for reading."); } - // Loop trough file + // Skip BOM, if any + switch ($this->_inputEncoding) { + case 'UTF-8': + fgets($fileHandle, 4) == "\xEF\xBB\xBF" ? + fseek($fileHandle, 3) : fseek($fileHandle, 0); + break; + + default: + break; + } + + // Loop through file $currentRow = 0; $rowData = array(); while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { @@ -193,6 +231,11 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader // Unescape enclosures $rowData[$i] = str_replace("\\" . $this->_enclosure, $this->_enclosure, $rowData[$i]); $rowData[$i] = str_replace($this->_enclosure . $this->_enclosure, $this->_enclosure, $rowData[$i]); + + // Convert encoding if necessary + if ($this->_inputEncoding !== 'UTF-8') { + $rowData[$i] = PHPExcel_Shared_String::ConvertEncoding($rowData[$i], 'UTF-8', $this->_inputEncoding); + } // Set cell value $objPHPExcel->getActiveSheet()->setCellValue( diff --git a/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php b/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php index 8d8d83488..63c5ae3cc 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php +++ b/libraries/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/IReadFilter.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter { diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php b/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php new file mode 100644 index 000000000..89d5a83c3 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel2003XML.php @@ -0,0 +1,698 @@ +_readDataOnly; + } + + /** + * Set read data only + * + * @param boolean $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadDataOnly($pValue = false) { + $this->_readDataOnly = $pValue; + return $this; + } + + /** + * Get which sheets to load + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } + + /** + * Set which sheets to load + * + * @param mixed $value + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadSheetsOnly($value = null) + { + $this->_loadSheetsOnly = is_array($value) ? + $value : array($value); + return $this; + } + + /** + * Set all sheets to load + * + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = null; + return $this; + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } + + /** + * Create a new PHPExcel_Reader_Excel2003XML + */ + public function __construct() { + $this->_sheetIndex = 0; + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFileName + * @return boolean + */ + public function canRead($pFilename) + { + +// Office xmlns:o="urn:schemas-microsoft-com:office:office" +// Excel xmlns:x="urn:schemas-microsoft-com:office:excel" +// XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" +// Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" +// XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" +// XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" +// MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset" +// Rowset xmlns:z="#RowsetSchema" +// + + $signature = array( + '', + '' + ); + + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Read sample data (first 2 KB will do) + $fh = fopen($pFilename, 'r'); + $data = fread($fh, 2048); + fclose($fh); + + $headers = explode("\n",$data); + $valid = true; + foreach($signature as $key => $match) { + if (isset($headers[$key])) { + $line = trim(rtrim($headers[$key], "\r\n")); + if ($line != $match) { + $valid = false; + break; + } + } else { + $valid = false; + break; + } + } + + return $valid; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } + + /** + * pixel units to excel width units(units of 1/256th of a character width) + * @param pxs + * @return + */ + private static function _pixel2WidthUnits($pxs) { + $UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219); + + $widthUnits = 256 * ($pxs / 7); + $widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)]; + return $widthUnits; + } + + /** + * excel width units(units of 1/256th of a character width) to pixel units + * @param widthUnits + * @return + */ + private static function _widthUnits2Pixel($widthUnits) { + $pixels = ($widthUnits / 256) * 7; + $offsetWidthUnits = $widthUnits % 256; + $pixels += round($offsetWidthUnits / (256 / 7)); + return $pixels; + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @throws Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); + + $underlineStyles = array ( + PHPExcel_Style_Font::UNDERLINE_NONE, + PHPExcel_Style_Font::UNDERLINE_DOUBLE, + PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING, + PHPExcel_Style_Font::UNDERLINE_SINGLE, + PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING + ); + $verticalAlignmentStyles = array ( + PHPExcel_Style_Alignment::VERTICAL_BOTTOM, + PHPExcel_Style_Alignment::VERTICAL_TOP, + PHPExcel_Style_Alignment::VERTICAL_CENTER, + PHPExcel_Style_Alignment::VERTICAL_JUSTIFY + ); + $horizontalAlignmentStyles = array ( + PHPExcel_Style_Alignment::HORIZONTAL_GENERAL, + PHPExcel_Style_Alignment::HORIZONTAL_LEFT, + PHPExcel_Style_Alignment::HORIZONTAL_RIGHT, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS, + PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY + ); + + + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $xml = simplexml_load_file($pFilename); + $namespaces = $xml->getNamespaces(true); +// echo '
';
+//		print_r($namespaces);
+//		echo '

'; +// +// echo '
';
+//		print_r($xml);
+//		echo '

'; +// + $docProps = $objPHPExcel->getProperties(); + foreach($xml->DocumentProperties[0] as $propertyName => $propertyValue) { + switch ($propertyName) { + case 'Title' : + $docProps->setTitle($propertyValue); + break; + case 'Subject' : + $docProps->setSubject($propertyValue); + break; + case 'Author' : + $docProps->setCreator($propertyValue); + break; + case 'Created' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'LastAuthor' : + $docProps->setLastModifiedBy($propertyValue); + break; + case 'Company' : + $docProps->setCompany($propertyValue); + break; + case 'Category' : + $docProps->setCategory($propertyValue); + break; + case 'Keywords' : + $docProps->setKeywords($propertyValue); + break; + case 'Description' : + $docProps->setDescription($propertyValue); + break; + } + } + + + foreach($xml->Styles[0] as $style) { + $style_ss = $style->attributes($namespaces['ss']); + $styleID = (string) $style_ss['ID']; +// echo 'Style ID = '.$styleID.'
'; + if ($styleID == 'Default') { + $this->_styles['Default'] = array(); + } else { + $this->_styles[$styleID] = $this->_styles['Default']; + } + foreach ($style as $styleType => $styleData) { + $styleAttributes = $styleData->attributes($namespaces['ss']); +// echo $styleType.'
'; + switch ($styleType) { + case 'Alignment' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'Vertical' : + if (self::identifyFixedStyleValue($verticalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['vertical'] = $styleAttributeValue; + } + break; + case 'Horizontal' : + if (self::identifyFixedStyleValue($horizontalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['horizontal'] = $styleAttributeValue; + } + break; + case 'WrapText' : + $this->_styles[$styleID]['alignment']['wrap'] = true; + break; + } + } + break; + case 'Borders' : + foreach($styleData->Border as $borderStyle) { + $borderAttributes = $borderStyle->attributes($namespaces['ss']); + $thisBorder = array(); + foreach($borderAttributes as $borderStyleKey => $borderStyleValue) { +// echo $borderStyleKey.' = '.$borderStyleValue.'
'; + switch ($borderStyleKey) { + case 'LineStyle' : + $thisBorder['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Weight' : +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Position' : + $borderPosition = strtolower($borderStyleValue); + break; + case 'Color' : + $borderColour = substr($borderStyleValue,1); + $thisBorder['color']['rgb'] = $borderColour; + break; + } + } + if (count($thisBorder) > 0) { + if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) { + $this->_styles[$styleID]['borders'][$borderPosition] = $thisBorder; + } + } + } + break; + case 'Font' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'FontName' : + $this->_styles[$styleID]['font']['name'] = $styleAttributeValue; + break; + case 'Size' : + $this->_styles[$styleID]['font']['size'] = $styleAttributeValue; + break; + case 'Color' : + $this->_styles[$styleID]['font']['color']['rgb'] = substr($styleAttributeValue,1); + break; + case 'Bold' : + $this->_styles[$styleID]['font']['bold'] = true; + break; + case 'Italic' : + $this->_styles[$styleID]['font']['italic'] = true; + break; + case 'Underline' : + if (self::identifyFixedStyleValue($underlineStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['font']['underline'] = $styleAttributeValue; + } + break; + } + } + break; + case 'Interior' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + switch ($styleAttributeKey) { + case 'Color' : + $this->_styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue,1); + break; + } + } + break; + case 'NumberFormat' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + $styleAttributeValue = str_replace($fromFormats,$toFormats,$styleAttributeValue); + switch ($styleAttributeValue) { + case 'Short Date' : + $styleAttributeValue = 'dd/mm/yyyy'; + break; + } + if ($styleAttributeValue > '') { + $this->_styles[$styleID]['numberformat']['code'] = $styleAttributeValue; + } + } + break; + case 'Protection' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
'; + } + break; + } + } +// print_r($this->_styles[$styleID]); +// echo '
'; + } +// echo '
'; + + $worksheetID = 0; + foreach($xml->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); + if ((isset($this->_loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && + (!in_array($worksheet_ss['Name'], $this->_loadSheetsOnly))) { + continue; + } + + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheet_ss['Name'])) { + $worksheetName = $worksheet_ss['Name']; + $objPHPExcel->getActiveSheet()->setTitle($worksheetName); + } + + $columnID = 'A'; + foreach($worksheet->Table->Column as $columnData) { + $columnData_ss = $columnData->attributes($namespaces['ss']); + if (isset($columnData_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1); + } + if (isset($columnData_ss['Width'])) { + $columnWidth = $columnData_ss['Width']; +// echo 'Setting column width for '.$columnID.' to '.$columnWidth.'
'; + $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); + } + ++$columnID; + } + + $rowID = 1; + foreach($worksheet->Table->Row as $rowData) { + $row_ss = $rowData->attributes($namespaces['ss']); + if (isset($row_ss['Index'])) { + $rowID = (integer) $row_ss['Index']; + } +// echo 'Row '.$rowID.'
'; + if (isset($row_ss['StyleID'])) { + $rowStyle = $row_ss['StyleID']; + } + if (isset($row_ss['Height'])) { + $rowHeight = $row_ss['Height']; +// echo 'Setting row height to '.$rowHeight.'
'; + $objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); + } + $columnID = 'A'; + foreach($rowData->Cell as $cell) { + + $cell_ss = $cell->attributes($namespaces['ss']); + if (isset($cell_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1); + } + $cellRange = $columnID.$rowID; + + if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) { + $columnTo = $columnID; + if (isset($cell_ss['MergeAcross'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1); + } + $rowTo = $rowID; + if (isset($cell_ss['MergeDown'])) { + $rowTo = $rowTo + $cell_ss['MergeDown']; + } + $cellRange .= ':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + + $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cell_ss['Formula'])) { + $cellDataFormula = $cell_ss['Formula']; + $hasCalculatedValue = true; + } + if (isset($cell->Data)) { + $cellValue = $cellData = $cell->Data; + $type = PHPExcel_Cell_DataType::TYPE_NULL; + $cellData_ss = $cellData->attributes($namespaces['ss']); + if (isset($cellData_ss['Type'])) { + $cellDataType = $cellData_ss['Type']; + switch ($cellDataType) { + /* + const TYPE_STRING = 's'; + const TYPE_FORMULA = 'f'; + const TYPE_NUMERIC = 'n'; + const TYPE_BOOL = 'b'; + const TYPE_NULL = 's'; + const TYPE_INLINE = 'inlineStr'; + const TYPE_ERROR = 'e'; + */ + case 'String' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + break; + case 'Number' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = (float) $cellValue; + if (floor($cellValue) == $cellValue) { + $cellValue = (integer) $cellValue; + } + break; + case 'Boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $cellValue = ($cellValue != 0); + break; + case 'DateTime' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue)); + break; + case 'Error' : + $type = PHPExcel_Cell_DataType::TYPE_ERROR; + break; + } + } + if ($hasCalculatedValue) { + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + $columnNumber = PHPExcel_Cell::columnIndexFromString($columnID); + // Convert R1C1 style references to A1 style references (but only when not quoted) + $temp = explode('"',$cellDataFormula); + foreach($temp as $key => &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if (($key % 2) == 0) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $rowID; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $rowID + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $columnNumber; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $columnNumber + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); + } + +// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'
'; +// + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$cellValue.'
'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue); + } + } + if (isset($cell_ss['StyleID'])) { + $style = (string) $cell_ss['StyleID']; +// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'
'; + if ((isset($this->_styles[$style])) && (count($this->_styles[$style]) > 0)) { +// echo 'Cell '.$columnID.$rowID.'
'; +// print_r($this->_styles[$style]); +// echo '
'; + if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { + $objPHPExcel->getActiveSheet()->setCellValue($columnID.$rowID,NULL); + } + $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->_styles[$style]); + } + } + ++$columnID; + } + ++$rowID; + } + ++$worksheetID; + } + + // Return + return $objPHPExcel; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_Excel2003XML + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php b/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php index cd0d5c1f2..6cbc89372 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel2007.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -94,7 +94,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader { @@ -217,7 +217,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $zip = new ZipArchive; if ($zip->open($pFilename) === true) { // check if it is an OOXML archive - $rels = simplexml_load_string($zip->getFromName("_rels/.rels")); + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); $zip->close(); @@ -227,7 +227,6 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader return false; } - private function _castToBool($c) { // echo 'Initial Cast to Boolean
'; $value = isset($c->v) ? (string) $c->v : null; @@ -299,7 +298,33 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - + + public function _getFromZipArchive(ZipArchive $archive, $fileName = '') + { + // Root-relative paths + if (strpos($fileName, '//') !== false) + { + $fileName = substr($fileName, strpos($fileName, '//') + 1); + } + $fileName = PHPExcel_Shared_File::realpath($fileName); + + // Apache POI fixes + $contents = $archive->getFromName($fileName); + if ($contents === false) + { + $contents = $archive->getFromName(substr($fileName, 1)); + } + + /* + if (strpos($contents, 'open($pFilename); - $rels = simplexml_load_string($zip->getFromName("_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($rels->Relationship as $rel) { switch ($rel["Type"]) { case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": - $xmlCore = simplexml_load_string($zip->getFromName("{$rel['Target']}")); - if ($xmlCore === false) { // Apache POI hack - $xmlCore = simplexml_load_string($zip->getFromName(substr("{$rel['Target']}", 1))); - } + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); if ($xmlCore) { $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); @@ -351,15 +373,12 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": $dir = dirname($rel["Target"]); - $relsWorkbook = simplexml_load_string($zip->getFromName("$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - if ($relsWorkbook === false) { // Apache POI hack - $relsWorkbook = simplexml_load_string($zip->getFromName(substr("$dir/_rels/" . basename($rel["Target"]) . ".rels", 1))); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - } + $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); $sharedStrings = array(); $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); - $xmlStrings = simplexml_load_string($zip->getFromName("$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlStrings = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); if (isset($xmlStrings) && isset($xmlStrings->si)) { foreach ($xmlStrings->si as $val) { if (isset($val->t)) { @@ -380,7 +399,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $styles = array(); $cellStyles = array(); $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']")); - $xmlStyles = simplexml_load_string($zip->getFromName("$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlStyles = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); $numFmts = null; if ($xmlStyles && $xmlStyles->numFmts[0]) { $numFmts = $xmlStyles->numFmts[0]; @@ -415,12 +434,6 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader "border" => $xmlStyles->borders->border[intval($xf["borderId"])], "alignment" => $xf->alignment, "protection" => $xf->protection, - "applyAlignment" => (isset($xf["applyAlignment"]) && ((string)$xf["applyAlignment"] == 'true' || (string)$xf["applyAlignment"] == '1')), - "applyBorder" => (isset($xf["applyBorder"]) && ((string)$xf["applyBorder"] == 'true' || (string)$xf["applyBorder"] == '1')), - "applyFill" => (isset($xf["applyFill"]) && ((string)$xf["applyFill"] == 'true' || (string)$xf["applyFill"] == '1')), - "applyFont" => (isset($xf["applyFont"]) && ((string)$xf["applyFont"] == 'true' || (string)$xf["applyFont"] == '1')), - "applyNumberFormat" => (isset($xf["applyNumberFormat"]) && ((string)$xf["applyNumberFormat"] == 'true' || (string)$xf["applyNumberFormat"] == '1')), - "applyProtection" => (isset($xf["applyProtection"]) && ((string)$xf["applyProtection"] == 'true' || (string)$xf["applyProtection"] == '1')) ); $styles[] = $style; @@ -448,12 +461,6 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader "border" => $xmlStyles->borders->border[intval($xf["borderId"])], "alignment" => $xf->alignment, "protection" => $xf->protection, - "applyAlignment" => true, - "applyBorder" => true, - "applyFill" => true, - "applyFont" => true, - "applyNumberFormat" => true, - "applyProtection" => true ); $cellStyles[] = $cellStyle; @@ -466,29 +473,32 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $dxfs = array(); if (!$this->_readDataOnly && $xmlStyles) { - foreach ($xmlStyles->dxfs->dxf as $dxf) { - $style = new PHPExcel_Style; - $this->_readStyle($style, $dxf); - $dxfs[] = $style; + if ($xmlStyles->dxfs) { + foreach ($xmlStyles->dxfs->dxf as $dxf) { + $style = new PHPExcel_Style; + $this->_readStyle($style, $dxf); + $dxfs[] = $style; + } } - foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { - if (intval($cellStyle['builtinId']) == 0) { - if (isset($cellStyles[intval($cellStyle['xfId'])])) { - // Set default style - $style = new PHPExcel_Style; - $this->_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); - - // normal style, currently not using it for anything + if ($xmlStyles->cellStyles) + { + foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { + if (intval($cellStyle['builtinId']) == 0) { + if (isset($cellStyles[intval($cellStyle['xfId'])])) { + // Set default style + $style = new PHPExcel_Style; + $this->_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); + + // normal style, currently not using it for anything + } } } } } - $xmlWorkbook = simplexml_load_string($zip->getFromName("{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - if ($xmlWorkbook === false) { // Apache POI hack - $xmlWorkbook = simplexml_load_string($zip->getFromName(substr("{$rel['Target']}", 1))); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - } + $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + // Set base date if ($xmlWorkbook->workbookPr) { PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); @@ -505,816 +515,857 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $countSkippedSheets = 0; // keep track of number of skipped sheets $mapSheetId = array(); // mapping of sheet ids from old to new - foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { - ++$oldSheetId; - - // Check if sheet should be skipped - if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { - ++$countSkippedSheets; - $mapSheetId[$oldSheetId] = null; - continue; - } - - // Map old sheet id in original workbook to new sheet id. - // They will differ if loadSheetsOnly() is being used - $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; - - // Load sheet - $docSheet = $excel->createSheet(); - $docSheet->setTitle((string) $eleSheet["name"]); - $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $xmlSheet = simplexml_load_string($zip->getFromName("$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - - $sharedFormulas = array(); - - if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { - if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { - $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); + if ($xmlWorkbook->sheets) + { + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + ++$oldSheetId; + + // Check if sheet should be skipped + if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { + ++$countSkippedSheets; + $mapSheetId[$oldSheetId] = null; + continue; } - - if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { - $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); + + // Map old sheet id in original workbook to new sheet id. + // They will differ if loadSheetsOnly() is being used + $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; + + // Load sheet + $docSheet = $excel->createSheet(); + $docSheet->setTitle((string) $eleSheet["name"]); + $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $xmlSheet = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + + $sharedFormulas = array(); + + if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') { + $docSheet->setSheetState( (string) $eleSheet["state"] ); } - - if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { - $docSheet->setShowGridLines((string)$xmlSheet->sheetViews->sheetView['showGridLines'] ? true : false); - } - - if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { - $docSheet->setRightToLeft((string)$xmlSheet->sheetViews->sheetView['rightToLeft'] ? true : false); - } - - if (isset($xmlSheet->sheetViews->sheetView->pane)) { - if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { - $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); - } else { - $xSplit = 0; - $ySplit = 0; - - if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { - $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); - } - - if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { - $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); - } - - $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); - } - } - } - - if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { - if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && $xmlSheet->sheetPr->outlinePr['summaryRight'] == false) { - $docSheet->setShowSummaryRight(false); - } else { - $docSheet->setShowSummaryRight(true); - } - - if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && $xmlSheet->sheetPr->outlinePr['summaryBelow'] == false) { - $docSheet->setShowSummaryBelow(false); - } else { - $docSheet->setShowSummaryBelow(true); - } - } - - if (isset($xmlSheet->sheetFormatPr)) { - if (isset($xmlSheet->sheetFormatPr['customHeight']) && ((string)$xmlSheet->sheetFormatPr['customHeight'] == '1' || strtolower((string)$xmlSheet->sheetFormatPr['customHeight']) == 'true') && isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { - $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); - } - if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { - $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); - } - } - - if (isset($xmlSheet->cols) && !$this->_readDataOnly) { - foreach ($xmlSheet->cols->col as $col) { - for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { - if ($col["bestFit"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); - } - if ($col["hidden"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false); - } - if ($col["collapsed"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true); - } - if ($col["outlineLevel"] > 0) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); - } - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); - - if (intval($col["max"]) == 16384) { - break; + + if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { + if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { + $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); + } + + if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { + $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); + } + + if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { + $docSheet->setShowGridLines((string)$xmlSheet->sheetViews->sheetView['showGridLines'] ? true : false); + } + + if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { + $docSheet->setRightToLeft((string)$xmlSheet->sheetViews->sheetView['rightToLeft'] ? true : false); + } + + if (isset($xmlSheet->sheetViews->sheetView->pane)) { + if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { + $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); + } else { + $xSplit = 0; + $ySplit = 0; + + if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { + $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); + } + + if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { + $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); + } + + $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); + } + } + + if (isset($xmlSheet->sheetViews->sheetView->selection)) { + if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) { + $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref']; + $sqref = explode(' ', $sqref); + $sqref = $sqref[0]; + $docSheet->setSelectedCells($sqref); } } + } - } - - if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { - if ($xmlSheet->printOptions['gridLinesSet'] == 'true' && $xmlSheet->printOptions['gridLinesSet'] == '1') { - $docSheet->setShowGridlines(true); - } - - if ($xmlSheet->printOptions['gridLines'] == 'true' || $xmlSheet->printOptions['gridLines'] == '1') { - $docSheet->setPrintGridlines(true); - } - - if ($xmlSheet->printOptions['horizontalCentered']) { - $docSheet->getPageSetup()->setHorizontalCentered(true); - } - if ($xmlSheet->printOptions['verticalCentered']) { - $docSheet->getPageSetup()->setVerticalCentered(true); - } - } - - if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { - foreach ($xmlSheet->sheetData->row as $row) { - if ($row["ht"] && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); - } - if ($row["hidden"] && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setVisible(false); - } - if ($row["collapsed"]) { - $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true); - } - if ($row["outlineLevel"] > 0) { - $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); - } - - foreach ($row->c as $c) { - $r = (string) $c["r"]; - $cellDataType = (string) $c["t"]; - $value = null; - $calculatedValue = null; - - // Read cell? - if (!is_null($this->getReadFilter())) { - $coordinates = PHPExcel_Cell::coordinateFromString($r); - - if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { - break; - } - } - -// echo 'Reading cell '.$coordinates[0].$coordinates[1].'
'; -// print_r($c); -// echo '
'; -// echo 'Cell Data Type is '.$cellDataType.': '; -// - // Read cell! - switch ($cellDataType) { - case "s": -// echo 'String
'; - if ((string)$c->v != '') { - $value = $sharedStrings[intval($c->v)]; - - if ($value instanceof PHPExcel_RichText) { - $value = clone $value; - } - } else { - $value = ''; - } - - break; - case "b": -// echo 'Boolean
'; - if (!isset($c->f)) { - $value = $this->_castToBool($c); - } else { - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool'); -// echo '$calculatedValue = '.$calculatedValue.'
'; - } - break; - case "inlineStr": -// echo 'Inline String
'; - $value = $this->_parseRichText($c->is); - - break; - case "e": -// echo 'Error
'; - if (!isset($c->f)) { - $value = $this->_castToError($c); - } else { - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); -// echo '$calculatedValue = '.$calculatedValue.'
'; - } - - break; - - default: -// echo 'Default
'; - if (!isset($c->f)) { -// echo 'Not a Formula
'; - $value = $this->_castToString($c); - } else { -// echo 'Treat as Formula
'; - // Formula - $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); -// echo '$calculatedValue = '.$calculatedValue.'
'; - } - - break; - } -// echo 'Value is '.$value.'
'; - - // Check for numeric values - if (is_numeric($value) && $cellDataType != 's') { - if ($value == (int)$value) $value = (int)$value; - elseif ($value == (float)$value) $value = (float)$value; - elseif ($value == (double)$value) $value = (double)$value; - } - - // Rich text? - if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { - $value = $value->getPlainText(); - } - - // Assign value - if ($cellDataType != '') { - $docSheet->setCellValueExplicit($r, $value, $cellDataType); - } else { - $docSheet->setCellValue($r, $value); - } - if (!is_null($calculatedValue)) { - $docSheet->getCell($r)->setCalculatedValue($calculatedValue); - } - - // Style information? - if ($c["s"] && !$this->_readDataOnly) { - // no style index means 0, it seems - $docSheet->getCell($r)->setXfIndex(isset($styles[intval($c["s"])]) ? - intval($c["s"]) : 0); - } - - // Set rich text parent - if ($value instanceof PHPExcel_RichText && !$this->_readDataOnly) { - $value->setParent($docSheet->getCell($r)); - } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) { + if (isset($xmlSheet->sheetPr->tabColor['rgb'])) { + $docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] ); } } - } - - $conditionals = array(); - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { - foreach ($xmlSheet->conditionalFormatting as $conditional) { - foreach ($conditional->cfRule as $cfRule) { - if ( - ( - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || - (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT - ) && isset($dxfs[intval($cfRule["dxfId"])]) - ) { - $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; - } - } - } - - foreach ($conditionals as $ref => $cfRules) { - ksort($cfRules); - $conditionalStyles = array(); - foreach ($cfRules as $cfRule) { - $objConditional = new PHPExcel_Style_Conditional(); - $objConditional->setConditionType((string)$cfRule["type"]); - $objConditional->setOperatorType((string)$cfRule["operator"]); - - if ((string)$cfRule["text"] != '') { - $objConditional->setText((string)$cfRule["text"]); - } - - if (count($cfRule->formula) > 1) { - foreach ($cfRule->formula as $formula) { - $objConditional->addCondition((string)$formula); - } - } else { - $objConditional->addCondition((string)$cfRule->formula); - } - $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); - $conditionalStyles[] = $objConditional; - } - - // Extract all cell references in $ref - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); - foreach ($aReferences as $reference) { - $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); - } - } - } - - $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { - foreach ($aKeys as $key) { - $method = "set" . ucfirst($key); - $docSheet->getProtection()->$method($xmlSheet->sheetProtection[$key] == "true"); - } - } - - if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { - $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true); - if ($xmlSheet->protectedRanges->protectedRange) { - foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { - $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); - } - } - } - - if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { - $docSheet->setAutoFilter((string) $xmlSheet->autoFilter["ref"]); - } - - if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { - foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { - $docSheet->mergeCells((string) $mergeCell["ref"]); - } - } - - if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { - $docPageMargins = $docSheet->getPageMargins(); - $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); - $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); - $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); - $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); - $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); - $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); - } - - if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { - $docPageSetup = $docSheet->getPageSetup(); - - if (isset($xmlSheet->pageSetup["orientation"])) { - $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); - } - if (isset($xmlSheet->pageSetup["paperSize"])) { - $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); - } - if (isset($xmlSheet->pageSetup["scale"])) { - $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"])); - } - if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) > 0) { - $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"])); - } - if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) > 0) { - $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"])); - } - } - - if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { - $docHeaderFooter = $docSheet->getHeaderFooter(); - - if (isset($xmlSheet->headerFooter["differentOddEven"]) && - ((string)$xmlSheet->headerFooter["differentOddEven"] == 'true' || (string)$xmlSheet->headerFooter["differentOddEven"] == '1')) { - $docHeaderFooter->setDifferentOddEven(true); - } else { - $docHeaderFooter->setDifferentOddEven(false); - } - if (isset($xmlSheet->headerFooter["differentFirst"]) && - ((string)$xmlSheet->headerFooter["differentFirst"] == 'true' || (string)$xmlSheet->headerFooter["differentFirst"] == '1')) { - $docHeaderFooter->setDifferentFirst(true); - } else { - $docHeaderFooter->setDifferentFirst(false); - } - if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && - ((string)$xmlSheet->headerFooter["scaleWithDoc"] == 'false' || (string)$xmlSheet->headerFooter["scaleWithDoc"] == '0')) { - $docHeaderFooter->setScaleWithDocument(false); - } else { - $docHeaderFooter->setScaleWithDocument(true); - } - if (isset($xmlSheet->headerFooter["alignWithMargins"]) && - ((string)$xmlSheet->headerFooter["alignWithMargins"] == 'false' || (string)$xmlSheet->headerFooter["alignWithMargins"] == '0')) { - $docHeaderFooter->setAlignWithMargins(false); - } else { - $docHeaderFooter->setAlignWithMargins(true); - } - - $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); - $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); - $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); - $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); - $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); - $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); - } - - if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { - foreach ($xmlSheet->rowBreaks->brk as $brk) { - if ($brk["man"]) { - $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); - } - } - } - if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) { - foreach ($xmlSheet->colBreaks->brk as $brk) { - if ($brk["man"]) { - $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex($brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); - } - } - } - - if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { - foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { - // Uppercase coordinate - $range = strtoupper($dataValidation["sqref"]); - - // Extract all cell references in $range - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($range); - foreach ($aReferences as $reference) { - // Create validation - $docValidation = $docSheet->getCell($reference)->getDataValidation(); - $docValidation->setType((string) $dataValidation["type"]); - $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); - $docValidation->setOperator((string) $dataValidation["operator"]); - $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); - $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); - $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); - $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); - $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); - $docValidation->setError((string) $dataValidation["error"]); - $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); - $docValidation->setPrompt((string) $dataValidation["prompt"]); - $docValidation->setFormula1((string) $dataValidation->formula1); - $docValidation->setFormula2((string) $dataValidation->formula2); - } - } - } - - // Add hyperlinks - $hyperlinks = array(); - if (!$this->_readDataOnly) { - // Locate hyperlink relations - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { - $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; - } - } - } - - // Loop trough hyperlinks - if ($xmlSheet && $xmlSheet->hyperlinks) { - foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { - // Link url - $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); - - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { - if (isset($linkRel['id'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] ); - } - if (isset($hyperlink['location'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); - } - - // Tooltip - if (isset($hyperlink['tooltip'])) { - $docSheet->getCell( $cellReference )->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); - } - } - } - } - } - - // Add comments - $comments = array(); - $vmlComments = array(); - if (!$this->_readDataOnly) { - // Locate comment relations - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { - $comments[(string)$ele["Id"]] = (string)$ele["Target"]; - } - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { - $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; - } - } - } - - // Loop trough comments - foreach ($comments as $relName => $relPath) { - // Load comments file - $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $commentsFile = simplexml_load_string($zip->getFromName($relPath) ); - - // Utility variables - $authors = array(); - - // Loop trough authors - foreach ($commentsFile->authors->author as $author) { - $authors[] = (string)$author; - } - - // Loop trough contents - foreach ($commentsFile->commentList->comment as $comment) { - $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); - $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); - } - } - - // Loop trough VML comments - foreach ($vmlComments as $relName => $relPath) { - // Load VML comments file - $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $vmlCommentsFile = simplexml_load_string( $zip->getFromName($relPath) ); - $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - - $shapes = $vmlCommentsFile->xpath('//v:shape'); - foreach ($shapes as $shape) { - $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - - if (isset($shape['style'])) { - $style = (string)$shape['style']; - $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); - $column = null; - $row = null; - - $clientData = $shape->xpath('.//x:ClientData'); - if (is_array($clientData)) { - $clientData = $clientData[0]; - - if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { - $temp = $clientData->xpath('.//x:Row'); - if (is_array($temp)) $row = $temp[0]; - - $temp = $clientData->xpath('.//x:Column'); - if (is_array($temp)) $column = $temp[0]; - } - } - - if (!is_null($column) && !is_null($row)) { - // Set comment properties - $comment = $docSheet->getCommentByColumnAndRow($column, $row + 1); - $comment->getFillColor()->setRGB( $fillColor ); - - // Parse style - $styleArray = explode(';', str_replace(' ', '', $style)); - foreach ($styleArray as $stylePair) { - $stylePair = explode(':', $stylePair); - - if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); - if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); - if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); - if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); - if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); - - } - } - } - } - } - - // Header/footer images - if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $vmlRelationship = ''; - - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { - $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); - } - } - - if ($vmlRelationship != '') { - // Fetch linked images - $relsVML = simplexml_load_string($zip->getFromName( dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $drawings = array(); - foreach ($relsVML->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { - $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); - } - } - - // Fetch VML document - $vmlDrawing = simplexml_load_string($zip->getFromName($vmlRelationship)); - $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - - $hfImages = array(); - - $shapes = $vmlDrawing->xpath('//v:shape'); - foreach ($shapes as $shape) { - $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); - $imageData = $shape->xpath('//v:imagedata'); - $imageData = $imageData[0]; - - $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); - $style = self::toCSSArray( (string)$shape['style'] ); - - $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); - if (isset($imageData['title'])) { - $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); - } - - $hfImages[ (string)$shape['id'] ]->setPath("zip://$pFilename#" . $drawings[(string)$imageData['relid']], false); - $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); - $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); - $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); - $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); - $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); - $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); - } - - $docSheet->getHeaderFooter()->setImages($hfImages); - } - } - } - - } - -// TODO: Make sure drawings and graph are loaded differently! - if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($zip->getFromName( dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $drawings = array(); - foreach ($relsWorksheet->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { - $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); - } - } - if ($xmlSheet->drawing && !$this->_readDataOnly) { - foreach ($xmlSheet->drawing as $drawing) { - $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $relsDrawing = simplexml_load_string($zip->getFromName( dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - $images = array(); - - if ($relsDrawing && $relsDrawing->Relationship) { - foreach ($relsDrawing->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { - $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]); - } - } - } - $xmlDrawing = simplexml_load_string($zip->getFromName($fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); - - if ($xmlDrawing->oneCellAnchor) { - foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { - if ($oneCellAnchor->pic->blipFill) { - $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; - $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; - $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; - $objDrawing = new PHPExcel_Worksheet_Drawing; - $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); - $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); - $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); - $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); - $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); - $objDrawing->setResizeProportional(false); - $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx"))); - $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy"))); - if ($xfrm) { - $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); - } - if ($outerShdw) { - $shadow = $objDrawing->getShadow(); - $shadow->setVisible(true); - $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); - $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); - $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); - $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); - $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); - $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); - } - $objDrawing->setWorksheet($docSheet); - } - } - } - if ($xmlDrawing->twoCellAnchor) { - foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { - if ($twoCellAnchor->pic->blipFill) { - $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; - $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; - $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; - $objDrawing = new PHPExcel_Worksheet_Drawing; - $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); - $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); - $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); - $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); - $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); - $objDrawing->setResizeProportional(false); - - $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); - $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); - - if ($xfrm) { - $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); - } - if ($outerShdw) { - $shadow = $objDrawing->getShadow(); - $shadow->setVisible(true); - $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); - $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); - $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); - $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); - $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); - $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); - } - $objDrawing->setWorksheet($docSheet); - } - } - } - - } - } - } - - // Loop trough definedNames - if ($xmlWorkbook->definedNames) { - foreach ($xmlWorkbook->definedNames->definedName as $definedName) { - // Extract range - $extractedRange = (string)$definedName; - $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); - $extractedRange = str_replace('$', '', $extractedRange); - - // Valid range? - if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { - continue; - } - - // Some definedNames are only applicable if we are on the same sheet... - if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { - // Switch on type - switch ((string)$definedName['name']) { - - case '_xlnm._FilterDatabase': - $docSheet->setAutoFilter($extractedRange); - break; - - case '_xlnm.Print_Titles': - // Split $extractedRange - $extractedRange = explode(',', $extractedRange); - - // Set print titles - if (isset($extractedRange[0])) { - $range = explode(':', $extractedRange[0]); - - if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') - $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); - $range[0] = str_replace('$', '', $range[0]); - if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') - $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); - $range[1] = str_replace('$', '', $range[1]); - - $docSheet->getPageSetup()->setColumnsToRepeatAtLeft( $range ); - } - if (isset($extractedRange[1])) { - $range = explode(':', $extractedRange[1]); - - if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') - $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); - $range[0] = str_replace('$', '', $range[0]); - if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') - $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); - $range[1] = str_replace('$', '', $range[1]); - - $docSheet->getPageSetup()->setRowsToRepeatAtTop( $range ); - } - - break; - - case '_xlnm.Print_Area': - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - - $docSheet->getPageSetup()->setPrintArea($extractedRange); - break; - - default: - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, true) ); - break; - } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { + if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && $xmlSheet->sheetPr->outlinePr['summaryRight'] == false) { + $docSheet->setShowSummaryRight(false); } else { - // "Global" definedNames - $locatedSheet = null; - $extractedSheetName = ''; - if (strpos( (string)$definedName, '!' ) !== false) { - // Extract sheet name - $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); - $extractedSheetName = $extractedSheetName[0]; - - // Locate sheet - $locatedSheet = $excel->getSheetByName($extractedSheetName); - - // Modify range - $range = explode('!', $extractedRange); - $extractedRange = isset($range[1]) ? $range[1] : $range[0]; - } - - if (!is_null($locatedSheet)) { - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); + $docSheet->setShowSummaryRight(true); + } + + if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && $xmlSheet->sheetPr->outlinePr['summaryBelow'] == false) { + $docSheet->setShowSummaryBelow(false); + } else { + $docSheet->setShowSummaryBelow(true); + } + } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { + if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && $xmlSheet->sheetPr->pageSetUpPr['fitToPage'] == false) { + $docSheet->getPageSetup()->setFitToPage(false); + } else { + $docSheet->getPageSetup()->setFitToPage(true); + } + } + + if (isset($xmlSheet->sheetFormatPr)) { + if (isset($xmlSheet->sheetFormatPr['customHeight']) && ((string)$xmlSheet->sheetFormatPr['customHeight'] == '1' || strtolower((string)$xmlSheet->sheetFormatPr['customHeight']) == 'true') && isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { + $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); + } + if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { + $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); + } + } + + if (isset($xmlSheet->cols) && !$this->_readDataOnly) { + foreach ($xmlSheet->cols->col as $col) { + for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { + if ($col["style"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); + } + if ($col["bestFit"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); + } + if ($col["hidden"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false); + } + if ($col["collapsed"]) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true); + } + if ($col["outlineLevel"] > 0) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); + } + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); + + if (intval($col["max"]) == 16384) { + break; + } } } } + + if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { + if ($xmlSheet->printOptions['gridLinesSet'] == 'true' && $xmlSheet->printOptions['gridLinesSet'] == '1') { + $docSheet->setShowGridlines(true); + } + + if ($xmlSheet->printOptions['gridLines'] == 'true' || $xmlSheet->printOptions['gridLines'] == '1') { + $docSheet->setPrintGridlines(true); + } + + if ($xmlSheet->printOptions['horizontalCentered']) { + $docSheet->getPageSetup()->setHorizontalCentered(true); + } + if ($xmlSheet->printOptions['verticalCentered']) { + $docSheet->getPageSetup()->setVerticalCentered(true); + } + } + + if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { + foreach ($xmlSheet->sheetData->row as $row) { + if ($row["ht"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); + } + if ($row["hidden"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setVisible(false); + } + if ($row["collapsed"]) { + $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true); + } + if ($row["outlineLevel"] > 0) { + $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); + } + if ($row["s"]) { + $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"])); + } + + foreach ($row->c as $c) { + $r = (string) $c["r"]; + $cellDataType = (string) $c["t"]; + $value = null; + $calculatedValue = null; + + // Read cell? + if (!is_null($this->getReadFilter())) { + $coordinates = PHPExcel_Cell::coordinateFromString($r); + + if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { + continue; + } + } + + // echo 'Reading cell '.$coordinates[0].$coordinates[1].'
'; + // print_r($c); + // echo '
'; + // echo 'Cell Data Type is '.$cellDataType.': '; + // + // Read cell! + switch ($cellDataType) { + case "s": + // echo 'String
'; + if ((string)$c->v != '') { + $value = $sharedStrings[intval($c->v)]; + + if ($value instanceof PHPExcel_RichText) { + $value = clone $value; + } + } else { + $value = ''; + } + + break; + case "b": + // echo 'Boolean
'; + if (!isset($c->f)) { + $value = $this->_castToBool($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool'); + // echo '$calculatedValue = '.$calculatedValue.'
'; + } + break; + case "inlineStr": + // echo 'Inline String
'; + $value = $this->_parseRichText($c->is); + + break; + case "e": + // echo 'Error
'; + if (!isset($c->f)) { + $value = $this->_castToError($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); + // echo '$calculatedValue = '.$calculatedValue.'
'; + } + + break; + + default: + // echo 'Default
'; + if (!isset($c->f)) { + // echo 'Not a Formula
'; + $value = $this->_castToString($c); + } else { + // echo 'Treat as Formula
'; + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); + // echo '$calculatedValue = '.$calculatedValue.'
'; + } + + break; + } + // echo 'Value is '.$value.'
'; + + // Check for numeric values + if (is_numeric($value) && $cellDataType != 's') { + if ($value == (int)$value) $value = (int)$value; + elseif ($value == (float)$value) $value = (float)$value; + elseif ($value == (double)$value) $value = (double)$value; + } + + // Rich text? + if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { + $value = $value->getPlainText(); + } + + // Assign value + if ($cellDataType != '') { + $docSheet->setCellValueExplicit($r, $value, $cellDataType); + } else { + $docSheet->setCellValue($r, $value); + } + if (!is_null($calculatedValue)) { + $docSheet->getCell($r)->setCalculatedValue($calculatedValue); + } + + // Style information? + if ($c["s"] && !$this->_readDataOnly) { + // no style index means 0, it seems + $docSheet->getCell($r)->setXfIndex(isset($styles[intval($c["s"])]) ? + intval($c["s"]) : 0); + } + + // Set rich text parent + if ($value instanceof PHPExcel_RichText && !$this->_readDataOnly) { + $value->setParent($docSheet->getCell($r)); + } + } + } + } + + $conditionals = array(); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { + foreach ($xmlSheet->conditionalFormatting as $conditional) { + foreach ($conditional->cfRule as $cfRule) { + if ( + ( + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + ) && isset($dxfs[intval($cfRule["dxfId"])]) + ) { + $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; + } + } + } + + foreach ($conditionals as $ref => $cfRules) { + ksort($cfRules); + $conditionalStyles = array(); + foreach ($cfRules as $cfRule) { + $objConditional = new PHPExcel_Style_Conditional(); + $objConditional->setConditionType((string)$cfRule["type"]); + $objConditional->setOperatorType((string)$cfRule["operator"]); + + if ((string)$cfRule["text"] != '') { + $objConditional->setText((string)$cfRule["text"]); + } + + if (count($cfRule->formula) > 1) { + foreach ($cfRule->formula as $formula) { + $objConditional->addCondition((string)$formula); + } + } else { + $objConditional->addCondition((string)$cfRule->formula); + } + $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); + $conditionalStyles[] = $objConditional; + } + + // Extract all cell references in $ref + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); + foreach ($aReferences as $reference) { + $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); + } + } + } + + $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + foreach ($aKeys as $key) { + $method = "set" . ucfirst($key); + $docSheet->getProtection()->$method($xmlSheet->sheetProtection[$key] == "true"); + } + } + + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true); + if ($xmlSheet->protectedRanges->protectedRange) { + foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { + $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); + } + } + } + + if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { + $docSheet->setAutoFilter((string) $xmlSheet->autoFilter["ref"]); + } + + if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { + foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { + $docSheet->mergeCells((string) $mergeCell["ref"]); + } + } + + if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { + $docPageMargins = $docSheet->getPageMargins(); + $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); + $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); + $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); + $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); + $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); + $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); + } + + if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { + $docPageSetup = $docSheet->getPageSetup(); + + if (isset($xmlSheet->pageSetup["orientation"])) { + $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); + } + if (isset($xmlSheet->pageSetup["paperSize"])) { + $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); + } + if (isset($xmlSheet->pageSetup["scale"])) { + $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), false); + } + if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) { + $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), false); + } + if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) { + $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), false); + } + if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) && + ((string)$xmlSheet->pageSetup["useFirstPageNumber"] == 'true' || (string)$xmlSheet->pageSetup["useFirstPageNumber"] == '1')) { + $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); + } + } + + if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { + $docHeaderFooter = $docSheet->getHeaderFooter(); + + if (isset($xmlSheet->headerFooter["differentOddEven"]) && + ((string)$xmlSheet->headerFooter["differentOddEven"] == 'true' || (string)$xmlSheet->headerFooter["differentOddEven"] == '1')) { + $docHeaderFooter->setDifferentOddEven(true); + } else { + $docHeaderFooter->setDifferentOddEven(false); + } + if (isset($xmlSheet->headerFooter["differentFirst"]) && + ((string)$xmlSheet->headerFooter["differentFirst"] == 'true' || (string)$xmlSheet->headerFooter["differentFirst"] == '1')) { + $docHeaderFooter->setDifferentFirst(true); + } else { + $docHeaderFooter->setDifferentFirst(false); + } + if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && + ((string)$xmlSheet->headerFooter["scaleWithDoc"] == 'false' || (string)$xmlSheet->headerFooter["scaleWithDoc"] == '0')) { + $docHeaderFooter->setScaleWithDocument(false); + } else { + $docHeaderFooter->setScaleWithDocument(true); + } + if (isset($xmlSheet->headerFooter["alignWithMargins"]) && + ((string)$xmlSheet->headerFooter["alignWithMargins"] == 'false' || (string)$xmlSheet->headerFooter["alignWithMargins"] == '0')) { + $docHeaderFooter->setAlignWithMargins(false); + } else { + $docHeaderFooter->setAlignWithMargins(true); + } + + $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); + $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); + $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); + $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); + $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); + $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); + } + + if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->rowBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); + } + } + } + if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->colBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex($brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); + } + } + } + + if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { + foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { + // Uppercase coordinate + $range = strtoupper($dataValidation["sqref"]); + + // Extract all cell references in $range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($range); + foreach ($aReferences as $reference) { + // Create validation + $docValidation = $docSheet->getCell($reference)->getDataValidation(); + $docValidation->setType((string) $dataValidation["type"]); + $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); + $docValidation->setOperator((string) $dataValidation["operator"]); + $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); + $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); + $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); + $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); + $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); + $docValidation->setError((string) $dataValidation["error"]); + $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); + $docValidation->setPrompt((string) $dataValidation["prompt"]); + $docValidation->setFormula1((string) $dataValidation->formula1); + $docValidation->setFormula2((string) $dataValidation->formula2); + } + } + } + + // Add hyperlinks + $hyperlinks = array(); + if (!$this->_readDataOnly) { + // Locate hyperlink relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { + $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } + + // Loop through hyperlinks + if ($xmlSheet && $xmlSheet->hyperlinks) { + foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { + // Link url + $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { + if (isset($linkRel['id'])) { + $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] ); + } + if (isset($hyperlink['location'])) { + $docSheet->getCell( $cellReference )->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); + } + + // Tooltip + if (isset($hyperlink['tooltip'])) { + $docSheet->getCell( $cellReference )->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); + } + } + } + } + } + + // Add comments + $comments = array(); + $vmlComments = array(); + if (!$this->_readDataOnly) { + // Locate comment relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { + $comments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } + + // Loop through comments + foreach ($comments as $relName => $relPath) { + // Load comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $commentsFile = simplexml_load_string($this->_getFromZipArchive($zip, $relPath) ); + + // Utility variables + $authors = array(); + + // Loop through authors + foreach ($commentsFile->authors->author as $author) { + $authors[] = (string)$author; + } + + // Loop through contents + foreach ($commentsFile->commentList->comment as $comment) { + $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); + $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); + } + } + + // Loop through VML comments + foreach ($vmlComments as $relName => $relPath) { + // Load VML comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $vmlCommentsFile = simplexml_load_string( $this->_getFromZipArchive($zip, $relPath) ); + $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + $shapes = $vmlCommentsFile->xpath('//v:shape'); + foreach ($shapes as $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + if (isset($shape['style'])) { + $style = (string)$shape['style']; + $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); + $column = null; + $row = null; + + $clientData = $shape->xpath('.//x:ClientData'); + if (is_array($clientData)) { + $clientData = $clientData[0]; + + if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { + $temp = $clientData->xpath('.//x:Row'); + if (is_array($temp)) $row = $temp[0]; + + $temp = $clientData->xpath('.//x:Column'); + if (is_array($temp)) $column = $temp[0]; + } + } + + if (!is_null($column) && !is_null($row)) { + // Set comment properties + $comment = $docSheet->getCommentByColumnAndRow($column, $row + 1); + $comment->getFillColor()->setRGB( $fillColor ); + + // Parse style + $styleArray = explode(';', str_replace(' ', '', $style)); + foreach ($styleArray as $stylePair) { + $stylePair = explode(':', $stylePair); + + if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); + if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); + if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); + if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); + if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); + + } + } + } + } + } + + // Header/footer images + if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $vmlRelationship = ''; + + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } + + if ($vmlRelationship != '') { + // Fetch linked images + $relsVML = simplexml_load_string($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsVML->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); + } + } + + // Fetch VML document + $vmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $vmlRelationship)); + $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + $hfImages = array(); + + $shapes = $vmlDrawing->xpath('//v:shape'); + foreach ($shapes as $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + $imageData = $shape->xpath('//v:imagedata'); + $imageData = $imageData[0]; + + $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); + $style = self::toCSSArray( (string)$shape['style'] ); + + $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); + if (isset($imageData['title'])) { + $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); + } + + $hfImages[ (string)$shape['id'] ]->setPath("zip://$pFilename#" . $drawings[(string)$imageData['relid']], false); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); + $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); + $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); + $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); + $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); + } + + $docSheet->getHeaderFooter()->setImages($hfImages); + } + } + } + + } + + // TODO: Make sure drawings and graph are loaded differently! + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { + $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } + if ($xmlSheet->drawing && !$this->_readDataOnly) { + foreach ($xmlSheet->drawing as $drawing) { + $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $relsDrawing = simplexml_load_string($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $images = array(); + + if ($relsDrawing && $relsDrawing->Relationship) { + foreach ($relsDrawing->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]); + } + } + } + $xmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); + + if ($xmlDrawing->oneCellAnchor) { + foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { + if ($oneCellAnchor->pic->blipFill) { + $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy"))); + if ($xfrm) { + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } + } + } + if ($xmlDrawing->twoCellAnchor) { + foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { + if ($twoCellAnchor->pic->blipFill) { + $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex($twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); + + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); + + if ($xfrm) { + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } + } + } + + } + } + } + + // Loop through definedNames + if ($xmlWorkbook->definedNames) { + foreach ($xmlWorkbook->definedNames->definedName as $definedName) { + // Extract range + $extractedRange = (string)$definedName; + $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); + $extractedRange = str_replace('$', '', $extractedRange); + + // Valid range? + if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { + continue; + } + + // Some definedNames are only applicable if we are on the same sheet... + if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { + // Switch on type + switch ((string)$definedName['name']) { + + case '_xlnm._FilterDatabase': + $docSheet->setAutoFilter($extractedRange); + break; + + case '_xlnm.Print_Titles': + // Split $extractedRange + $extractedRange = explode(',', $extractedRange); + + // Set print titles + if (isset($extractedRange[0])) { + $range = explode(':', $extractedRange[0]); + + if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') + $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); + $range[0] = str_replace('$', '', $range[0]); + if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') + $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); + $range[1] = str_replace('$', '', $range[1]); + + $docSheet->getPageSetup()->setColumnsToRepeatAtLeft( $range ); + } + if (isset($extractedRange[1])) { + $range = explode(':', $extractedRange[1]); + + if (PHPExcel_Worksheet::extractSheetTitle($range[0]) != '') + $range[0] = PHPExcel_Worksheet::extractSheetTitle($range[0]); + $range[0] = str_replace('$', '', $range[0]); + if (PHPExcel_Worksheet::extractSheetTitle($range[1]) != '') + $range[1] = PHPExcel_Worksheet::extractSheetTitle($range[1]); + $range[1] = str_replace('$', '', $range[1]); + + $docSheet->getPageSetup()->setRowsToRepeatAtTop( $range ); + } + + break; + + case '_xlnm.Print_Area': + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + + $docSheet->getPageSetup()->setPrintArea($extractedRange); + break; + + default: + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, true) ); + break; + } + } else { + // "Global" definedNames + $locatedSheet = null; + $extractedSheetName = ''; + if (strpos( (string)$definedName, '!' ) !== false) { + // Extract sheet name + $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); + $extractedSheetName = $extractedSheetName[0]; + + // Locate sheet + $locatedSheet = $excel->getSheetByName($extractedSheetName); + + // Modify range + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + } + + if (!is_null($locatedSheet)) { + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); + } + } + } + } + + // Next sheet id + ++$sheetId; } - - // Next sheet id - ++$sheetId; } if (!$this->_readDataOnly) { @@ -1322,9 +1373,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index // keep active sheet index if sheet is still loaded, else first sheet is set as the active - if ($mapSheetId[$activeTab] !== null) { + if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) { $excel->setActiveSheetIndex($mapSheetId[$activeTab]); } else { + if ($excel->getSheetCount() == 0) + { + $excel->createSheet(); + } $excel->setActiveSheetIndex(0); } } @@ -1346,7 +1401,9 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader private function _readStyle($docStyle, $style) { // format code - if ($style->applyNumberFormat) $docStyle->getNumberFormat()->setFormatCode($style->numFmt); + if (isset($style->numFmt)) { + $docStyle->getNumberFormat()->setFormatCode($style->numFmt); + } // font if (isset($style->font)) { @@ -1381,7 +1438,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // fill - if (isset($style->fill) && ($style->applyFill || $style instanceof SimpleXMLElement)) { + if (isset($style->fill)) { if ($style->fill->gradientFill) { $gradientFill = $style->fill->gradientFill[0]; $docStyle->getFill()->setFillType((string) $gradientFill["type"]); @@ -1404,11 +1461,23 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // border - if (isset($style->border) && ($style->applyBorder || $style instanceof SimpleXMLElement)) { - if ($style->border["diagonalUp"] == 'true') { + if (isset($style->border)) { + $diagonalUp = false; + $diagonalDown = false; + if ($style->border["diagonalUp"] == 'true' || $style->border["diagonalUp"] == 1) { + $diagonalUp = true; + } + if ($style->border["diagonalDown"] == 'true' || $style->border["diagonalDown"] == 1) { + $diagonalDown = true; + } + if ($diagonalUp == false && $diagonalDown == false) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp == true && $diagonalDown == false) { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); - } elseif ($style->border["diagonalDown"] == 'true') { + } elseif ($diagonalUp == false && $diagonalDown == true) { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } elseif ($diagonalUp == true && $diagonalDown == true) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); } $this->_readBorder($docStyle->getBorders()->getLeft(), $style->border->left); $this->_readBorder($docStyle->getBorders()->getRight(), $style->border->right); @@ -1418,7 +1487,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // alignment - if (isset($style->alignment) && ($style->applyAlignment || $style instanceof SimpleXMLElement)) { + if (isset($style->alignment)) { $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]); $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]); @@ -1436,7 +1505,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // protection - if (isset($style->protection) && $style->applyProtection) { + if (isset($style->protection)) { if (isset($style->protection['locked'])) { if ((string)$style->protection['locked'] == 'true') { $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED); diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel5.php b/libraries/PHPExcel/PHPExcel/Reader/Excel5.php index 0dcaa2941..8509b0801 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of ParseXL (used as the base for this class): @@ -107,6 +107,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Reader/DefaultReadFilter.php'; /** PHPExcel_Worksheet_MemoryDrawing */ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/MemoryDrawing.php'; +/** PHPExcel_Style_Borders */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Borders.php'; + /** * PHPExcel_Reader_Excel5 @@ -115,7 +118,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/MemoryDrawing.php'; * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader { @@ -129,6 +132,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_FORMULA = 0x0006; const XLS_Type_EOF = 0x000a; const XLS_Type_PROTECT = 0x0012; + const XLS_Type_OBJECTPROTECT = 0x0063; + const XLS_Type_SCENPROTECT = 0x00dd; const XLS_Type_PASSWORD = 0x0013; const XLS_Type_HEADER = 0x0014; const XLS_Type_FOOTER = 0x0015; @@ -137,6 +142,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_VERTICALPAGEBREAKS = 0x001a; const XLS_Type_HORIZONTALPAGEBREAKS = 0x001b; const XLS_Type_NOTE = 0x001c; + const XLS_Type_SELECTION = 0x001d; const XLS_Type_DATEMODE = 0x0022; const XLS_Type_LEFTMARGIN = 0x0026; const XLS_Type_RIGHTMARGIN = 0x0027; @@ -188,7 +194,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_FORMAT = 0x041e; const XLS_Type_SHAREDFMLA = 0x04bc; const XLS_Type_BOF = 0x0809; + const XLS_Type_SHEETPROTECTION = 0x0867; const XLS_Type_RANGEPROTECTION = 0x0868; + const XLS_Type_SHEETLAYOUT = 0x0862; + const XLS_Type_XFEXT = 0x087d; const XLS_Type_UNKNOWN = 0xffff; /** @@ -578,6 +587,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_FONT: $this->_readFont(); break; case self::XLS_Type_FORMAT: $this->_readFormat(); break; case self::XLS_Type_XF: $this->_readXf(); break; + case self::XLS_Type_XFEXT: $this->_readXfExt(); break; case self::XLS_Type_STYLE: $this->_readStyle(); break; case self::XLS_Type_PALETTE: $this->_readPalette(); break; case self::XLS_Type_SHEET: $this->_readSheet(); break; @@ -595,30 +605,57 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Cannot be resolved already in XF record, because PALETTE record comes afterwards if (!$this->_readDataOnly) { foreach ($this->_objFonts as $objFont) { - $color = $this->_readColor($objFont->colorIndex); - $objFont->getColor()->setRGB($color['rgb']); + if (isset($objFont->colorIndex)) { + $color = $this->_readColor($objFont->colorIndex); + $objFont->getColor()->setRGB($color['rgb']); + } } foreach ($this->_phpExcel->getCellXfCollection() as $objStyle) { // fill start and end color - $startColor = $this->_readColor($objStyle->getFill()->startcolorIndex); - $objStyle->getFill()->getStartColor()->setRGB($startColor['rgb']); + $fill = $objStyle->getFill(); - $endColor = $this->_readColor($objStyle->getFill()->endcolorIndex); - $objStyle->getFill()->getEndColor()->setRGB($endColor['rgb']); + if (isset($fill->startcolorIndex)) { + $startColor = $this->_readColor($fill->startcolorIndex); + $fill->getStartColor()->setRGB($startColor['rgb']); + } + + if (isset($fill->endcolorIndex)) { + $endColor = $this->_readColor($fill->endcolorIndex); + $fill->getEndColor()->setRGB($endColor['rgb']); + } // border colors - $borderTopColor = $this->_readColor($objStyle->getBorders()->getTop()->colorIndex); - $objStyle->getBorders()->getTop()->getColor()->setRGB($borderTopColor['rgb']); + $top = $objStyle->getBorders()->getTop(); + $right = $objStyle->getBorders()->getRight(); + $bottom = $objStyle->getBorders()->getBottom(); + $left = $objStyle->getBorders()->getLeft(); + $diagonal = $objStyle->getBorders()->getDiagonal(); - $borderRightColor = $this->_readColor($objStyle->getBorders()->getRight()->colorIndex); - $objStyle->getBorders()->getRight()->getColor()->setRGB($borderRightColor['rgb']); + if (isset($top->colorIndex)) { + $borderTopColor = $this->_readColor($top->colorIndex); + $top->getColor()->setRGB($borderTopColor['rgb']); + } - $borderBottomColor = $this->_readColor($objStyle->getBorders()->getBottom()->colorIndex); - $objStyle->getBorders()->getBottom()->getColor()->setRGB($borderBottomColor['rgb']); + if (isset($right->colorIndex)) { + $borderRightColor = $this->_readColor($right->colorIndex); + $right->getColor()->setRGB($borderRightColor['rgb']); + } - $borderLeftColor = $this->_readColor($objStyle->getBorders()->getLeft()->colorIndex); - $objStyle->getBorders()->getLeft()->getColor()->setRGB($borderLeftColor['rgb']); + if (isset($bottom->colorIndex)) { + $borderBottomColor = $this->_readColor($bottom->colorIndex); + $bottom->getColor()->setRGB($borderBottomColor['rgb']); + } + + if (isset($left->colorIndex)) { + $borderLeftColor = $this->_readColor($left->colorIndex); + $left->getColor()->setRGB($borderLeftColor['rgb']); + } + + if (isset($diagonal->colorIndex)) { + $borderDiagonalColor = $this->_readColor($diagonal->colorIndex); + $diagonal->getColor()->setRGB($borderDiagonalColor['rgb']); + } } } @@ -644,6 +681,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add sheet to PHPExcel object $this->_phpSheet = $this->_phpExcel->createSheet(); $this->_phpSheet->setTitle($sheet['name']); + $this->_phpSheet->setSheetState($sheet['sheetState']); $this->_pos = $sheet['offset']; @@ -698,6 +736,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_BOTTOMMARGIN: $this->_readBottomMargin(); break; case self::XLS_Type_PAGESETUP: $this->_readPageSetup(); break; case self::XLS_Type_PROTECT: $this->_readProtect(); break; + case self::XLS_Type_SCENPROTECT: $this->_readScenProtect(); break; + case self::XLS_Type_OBJECTPROTECT: $this->_readObjectProtect(); break; case self::XLS_Type_PASSWORD: $this->_readPassword(); break; case self::XLS_Type_DEFCOLWIDTH: $this->_readDefColWidth(); break; case self::XLS_Type_COLINFO: $this->_readColInfo(); break; @@ -719,8 +759,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_WINDOW2: $this->_readWindow2(); break; case self::XLS_Type_SCL: $this->_readScl(); break; case self::XLS_Type_PANE: $this->_readPane(); break; + case self::XLS_Type_SELECTION: $this->_readSelection(); break; case self::XLS_Type_MERGEDCELLS: $this->_readMergedCells(); break; case self::XLS_Type_HYPERLINK: $this->_readHyperLink(); break; + case self::XLS_Type_SHEETLAYOUT: $this->_readSheetLayout(); break; + case self::XLS_Type_SHEETPROTECTION: $this->_readSheetProtection(); break; case self::XLS_Type_RANGEPROTECTION: $this->_readRangeProtection(); break; //case self::XLS_Type_IMDATA: $this->_readImData(); break; case self::XLS_Type_CONTINUE: $this->_readContinue(); break; @@ -841,21 +884,22 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? + $extractedRanges = array(); foreach ($ranges as $range) { - // $range should look like this one of these + // $range should look like one of these // Foo!$C$7:$J$66 // Bar!$A$1:$IV$2 $explodes = explode('!', $range); + $sheetName = $explodes[0]; if (count($explodes) == 2) { - if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) { - $extractedRange = $explodes[1]; - $extractedRange = str_replace('$', '', $extractedRange); - $docSheet->getPageSetup()->setPrintArea($extractedRange); - } + $extractedRanges[] = str_replace('$', '', $explodes[1]); // C7:J66 } } + if ($docSheet = $this->_phpExcel->getSheetByName($sheetName)) { + $docSheet->getPageSetup()->setPrintArea(implode(',', $extractedRanges)); // C7:J66,A1:IV2 + } break; case pack('C', 0x07): @@ -1185,7 +1229,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 2; mask 0x0004; underlined (redundant in BIFF5-BIFF8) // bit: 3; mask 0x0008; strike $isStrike = (0x0008 & $this->_GetInt2d($recordData, 2)) >> 3; - if ($isStrike) $objFont->setStriketrough(true); + if ($isStrike) $objFont->setStrikethrough(true); // offset: 4; size: 2; colour index $colorIndex = $this->_GetInt2d($recordData, 4); @@ -1450,6 +1494,24 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 29-23; mask: 0x3F800000; right color $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & $this->_GetInt4d($recordData, 10)) >> 23; + // bit: 30; mask: 0x40000000; 1 = diagonal line from top left to right bottom + $diagonalDown = (0x40000000 & $this->_GetInt4d($recordData, 10)) >> 30 ? + true : false; + + // bit: 31; mask: 0x80000000; 1 = diagonal line from bottom left to top right + $diagonalUp = (0x80000000 & $this->_GetInt4d($recordData, 10)) >> 31 ? + true : false; + + if ($diagonalUp == false && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp == true && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); + } elseif ($diagonalUp == false && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } elseif ($diagonalUp == true && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); + } + // offset: 14; size: 4; // bit: 6-0; mask: 0x0000007F; top color $objStyle->getBorders()->getTop()->colorIndex = (0x0000007F & $this->_GetInt4d($recordData, 14)) >> 0; @@ -1457,6 +1519,14 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 13-7; mask: 0x00003F80; bottom color $objStyle->getBorders()->getBottom()->colorIndex = (0x00003F80 & $this->_GetInt4d($recordData, 14)) >> 7; + // bit: 20-14; mask: 0x001FC000; diagonal color + $objStyle->getBorders()->getDiagonal()->colorIndex = (0x001FC000 & $this->_GetInt4d($recordData, 14)) >> 14; + + // bit: 24-21; mask: 0x01E00000; diagonal style + if ($bordersDiagonalStyle = $this->_mapBorderStyle((0x01E00000 & $this->_GetInt4d($recordData, 14)) >> 21)) { + $objStyle->getBorders()->getDiagonal()->setBorderStyle($bordersDiagonalStyle); + } + // bit: 31-26; mask: 0xFC000000 fill pattern if ($fillType = $this->_mapFillPattern((0xFC000000 & $this->_GetInt4d($recordData, 14)) >> 26)) { $objStyle->getFill()->setFillType($fillType); @@ -1548,6 +1618,182 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * + */ + private function _readXfExt() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0x087D = repeated header + + // offset: 2; size: 2 + + // offset: 4; size: 8; not used + + // offset: 12; size: 2; record version + + // offset: 14; size: 2; index to XF record which this record modifies + $ixfe = $this->_GetInt2d($recordData, 14); + + // offset: 16; size: 2; not used + + // offset: 18; size: 2; number of extension properties that follow + $cexts = $this->_GetInt2d($recordData, 18); + + // start reading the actual extension data + $offset = 20; + while ($offset < $length) { + // extension type + $extType = $this->_GetInt2d($recordData, $offset); + + // extension length + $cb = $this->_GetInt2d($recordData, $offset + 2); + + // extension data + $extData = substr($recordData, $offset + 4, $cb); + + switch ($extType) { + case 4: // fill start color + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getStartColor()->setRGB($rgb); + unset($fill->startcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 5: // fill end color + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getEndColor()->setRGB($rgb); + unset($fill->endcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 7: // border color top + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $top = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getTop(); + $top->getColor()->setRGB($rgb); + unset($top->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 8: // border color bottom + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $bottom = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getBottom(); + $bottom->getColor()->setRGB($rgb); + unset($bottom->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 9: // border color left + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $left = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getLeft(); + $left->getColor()->setRGB($rgb); + unset($left->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 10: // border color right + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $right = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getRight(); + $right->getColor()->setRGB($rgb); + unset($right->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 11: // border color diagonal + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $diagonal = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getDiagonal(); + $diagonal->getColor()->setRGB($rgb); + unset($diagonal->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 13: // font color + $xclfType = $this->_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $font = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFont(); + $font->getColor()->setRGB($rgb); + unset($font->colorIndex); // normal color index does not apply, discard + } + } + break; + } + + $offset += $cb; + } + } + + } + /** * Read STYLE record */ @@ -1636,6 +1882,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 4; size: 1; sheet state $rec_typeFlag = ord($recordData{4}); + switch (ord($recordData{4})) { + case 0x00: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + case 0x01: $sheetState = PHPExcel_Worksheet::SHEETSTATE_HIDDEN; break; + case 0x02: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN; break; + default: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + } // offset: 5; size: 1; sheet type $rec_visibilityFlag = ord($recordData{5}); @@ -1650,7 +1902,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } $this->_sheets[] = array( 'name' => $rec_name, - 'offset' => $rec_offset + 'offset' => $rec_offset, + 'sheetState' => $sheetState, ); } @@ -1779,6 +2032,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $nlen = ord($recordData{3}); // offset: 4; size: 2; size of the formula data (it can happen that this is zero) + // note: there can also be additional data, this is not included in $flen $flen = $this->_GetInt2d($recordData, 4); // offset: 14; size: var; Name (Unicode string without length field) @@ -1786,7 +2040,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: var; size: $flen; formula data $offset = 14 + $string['size']; - $formulaStructure = pack('v', $flen) . substr($recordData, $offset, $flen); + $formulaStructure = pack('v', $flen) . substr($recordData, $offset); try { $formula = $this->_getFormulaFromStructure($formulaStructure); @@ -1882,7 +2136,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // look up limit position foreach ($spliceOffsets as $spliceOffset) { - if ($pos < $spliceOffset) { + // it can happen that the string is empty, therefore we need + // <= and not just < + if ($pos <= $spliceOffset) { $limitpos = $spliceOffset; break; } @@ -2320,12 +2576,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 1: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT); break; } - if (!$this->_isFitToPages) { - $this->_phpSheet->getPageSetup()->setScale($scale); - } else { - $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth); - $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight); - } + $this->_phpSheet->getPageSetup()->setScale($scale, false); + $this->_phpSheet->getPageSetup()->setFitToPage((bool) $this->_isFitToPages); + $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth, false); + $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight, false); } // offset: 16; size: 8; header margin (IEEE 754 floating-point value) @@ -2350,16 +2604,61 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // move stream pointer to next record $this->_pos += 4 + $length; - if (!$this->_readDataOnly) { - // offset: 0; size: 2; - - // bit 0, mask 0x01; sheet protection - $isSheetProtected = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; - switch ($isSheetProtected) { - case 0: break; - case 1: $this->_phpSheet->getProtection()->setSheet(true); break; - } + if ($this->_readDataOnly) { + return; } + + // offset: 0; size: 2; + + // bit 0, mask 0x01; 1 = sheet is protected + $bool = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; + $this->_phpSheet->getProtection()->setSheet((bool)$bool); + } + + /** + * SCENPROTECT + */ + private function _readScenProtect() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; + + // bit: 0, mask 0x01; 1 = scenarios are protected + $bool = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; + + $this->_phpSheet->getProtection()->setScenarios((bool)$bool); + } + + /** + * OBJECTPROTECT + */ + private function _readObjectProtect() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; + + // bit: 0, mask 0x01; 1 = objects are protected + $bool = (0x01 & $this->_GetInt2d($recordData, 0)) >> 0; + + $this->_phpSheet->getProtection()->setObjects((bool)$bool); } /** @@ -2444,6 +2743,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $this->_phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden); $this->_phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level); $this->_phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed); + $this->_phpSheet->getColumnDimensionByColumn($i)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -2476,8 +2776,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 6; size: 2; - // bit: 14-0; mask: 0x7FF; height of the row, in twips = 1/20 of a point - $height = (0x7FF & $this->_GetInt2d($recordData, 6)) >> 0; + // bit: 14-0; mask: 0x7FFF; height of the row, in twips = 1/20 of a point + $height = (0x7FFF & $this->_GetInt2d($recordData, 6)) >> 0; // bit: 15: mask: 0x8000; 0 = row has custom height; 1= row has default height $useDefaultHeight = (0x8000 & $this->_GetInt2d($recordData, 6)) >> 15; @@ -2504,11 +2804,15 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $isHidden = (0x00000020 & $this->_GetInt4d($recordData, 12)) >> 5; $this->_phpSheet->getRowDimension($r + 1)->setVisible(!$isHidden); - // bit: 7; mask: 0x00000080; 1 = row has explicit default format - $hasDefaultFormat = (0x00000080 & $this->_GetInt4d($recordData, 12)) >> 7; + // bit: 7; mask: 0x00000080; 1 = row has explicit format + $hasExplicitFormat = (0x00000080 & $this->_GetInt4d($recordData, 12)) >> 7; - // bit: 27-16; mask: 0x0FFF0000; only applies when hasDefaultFormat = 1; index to XF record + // bit: 27-16; mask: 0x0FFF0000; only applies when hasExplicitFormat = 1; index to XF record $xfIndex = (0x0FFF0000 & $this->_GetInt4d($recordData, 12)) >> 16; + + if ($hasExplicitFormat) { + $this->_phpSheet->getRowDimension($r + 1)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } } } @@ -2541,7 +2845,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 4; RK value $rknum = $this->_GetInt4d($recordData, 6); @@ -2549,7 +2853,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add style information if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell @@ -2584,7 +2888,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 4; index to SST record $index = $this->_GetInt4d($recordData, 6); @@ -2626,7 +2930,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add style information if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -2667,13 +2971,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: var; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, $offset); + $xfIndex = $this->_GetInt2d($recordData, $offset); // offset: var; size: 4; RK value $numValue = $this->_GetIEEE754($this->_GetInt4d($recordData, $offset + 2)); if (!$this->_readDataOnly) { // add style - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell value @@ -2710,13 +3014,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); $numValue = $this->_extractNumber(substr($recordData, 6, 8)); // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // add cell value @@ -2760,6 +3064,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // bit: 1; mask: 0x0002; 1 = calculate on open // bit: 2; mask: 0x0008; 1 = part of a shared formula $isPartOfSharedFormula = (bool) (0x0008 & $options); + + // WARNING: + // We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true + // the formula data may be ordinary formula data, therefore we need to check + // explicitly for the tExp token (0x01) + $isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01; + if ($isPartOfSharedFormula) { // part of shared formula which means there will be a formula with a tExp token and nothing else // get the base cell, grab tExp token @@ -2774,7 +3085,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 16: size: 4; not used // offset: 4; size: 2; XF index - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 8; result of the formula if ( (ord($recordData{6}) == 0) @@ -2827,7 +3138,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } // store the formula @@ -2939,7 +3250,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; index to XF record - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // offset: 6; size: 1; the boolean value or error value $boolErr = ord($recordData{6}); @@ -2965,7 +3276,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3000,8 +3311,8 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { - $xfindex = $this->_GetInt2d($recordData, 4 + 2 * $i); - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $xfIndex = $this->_GetInt2d($recordData, 4 + 2 * $i); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3037,7 +3348,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; XF index - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // add cell value // todo: what if string is very long? continue record @@ -3052,7 +3363,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell style if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } } @@ -3078,11 +3389,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Read cell? if ( !is_null($this->getReadFilter()) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { // offset: 4; size: 2; XF index - $xfindex = $this->_GetInt2d($recordData, 4); + $xfIndex = $this->_GetInt2d($recordData, 4); // add style information if (!$this->_readDataOnly) { - $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfindex]); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); } } @@ -3209,6 +3520,56 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * Read SELECTION record. There is one such record for each pane in the sheet. + */ + private function _readSelection() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 1; pane identifier + $paneId = ord($recordData{0}); + + // offset: 1; size: 2; index to row of the active cell + $r = $this->_GetInt2d($recordData, 1); + + // offset: 3; size: 2; index to column of the active cell + $c = $this->_GetInt2d($recordData, 3); + + // offset: 5; size: 2; index into the following cell range list to the + // entry that contains the active cell + $index = $this->_GetInt2d($recordData, 5); + + // offset: 7; size: var; cell range address list containing all selected cell ranges + $data = substr($recordData, 7); + $cellRangeAddressList = $this->_readBIFF5CellRangeAddressList($data); // note: also BIFF8 uses BIFF5 syntax + + $selectedCells = $cellRangeAddressList['cellRangeAddresses'][0]; + + // first row '1' + last row '16384' indicates that full column is selected (apparently also in BIFF8!) + if (preg_match('/^([A-Z]+1\:[A-Z]+)16384$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)16384$/', '${1}1048576', $selectedCells); + } + + // first row '1' + last row '65536' indicates that full column is selected + if (preg_match('/^([A-Z]+1\:[A-Z]+)65536$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)65536$/', '${1}1048576', $selectedCells); + } + + // first column 'A' + last column 'IV' indicates that full row is selected + if (preg_match('/^(A[0-9]+\:)IV([0-9]+)$/', $selectedCells)) { + $selectedCells = preg_replace('/^(A[0-9]+\:)IV([0-9]+)$/', '${1}XFD${2}', $selectedCells); + } + + $this->_phpSheet->setSelectedCells($selectedCells); + } + } + /** * MERGEDCELLS * @@ -3307,6 +3668,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader switch ($hyperlinkType) { case 'URL': + // section 5.58.2: Hyperlink containing a URL + // e.g. http://example.org/index.php + // offset: var; size: 16; GUID of URL Moniker $offset += 16; // offset: var; size: 4; size (in bytes) of character array of the URL including trailing zero word @@ -3318,21 +3682,73 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $offset += $us; break; + case 'local': + // section 5.58.3: Hyperlink to local file + // examples: + // mydoc.txt + // ../../somedoc.xls#Sheet!A1 + + // offset: var; size: 16; GUI of File Moniker + $offset += 16; + + // offset: var; size: 2; directory up-level count. + $upLevelCount = $this->_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 4; character count of the shortened file path and name, including trailing zero word + $sl = $this->_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size: sl; character array of the shortened file path and name in 8.3-DOS-format (compressed Unicode string) + $shortenedFilePath = substr($recordData, $offset, $sl); + $shortenedFilePath = $this->_encodeUTF16($shortenedFilePath, true); + $shortenedFilePath = substr($shortenedFilePath, 0, -1); // remove trailing zero + + $offset += $sl; + + // offset: var; size: 24; unknown sequence + $offset += 24; + + // extended file path + // offset: var; size: 4; size of the following file link field including string lenth mark + $sz = $this->_GetInt4d($recordData, $offset); + $offset += 4; + + // only present if $sz > 0 + if ($sz > 0) { + // offset: var; size: 4; size of the character array of the extended file path and name + $xl = $this->_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size 2; unknown + $offset += 2; + + // offset: var; size $xl; character array of the extended file path and name. + $extendedFilePath = substr($recordData, $offset, $xl); + $extendedFilePath = $this->_encodeUTF16($extendedFilePath, false); + $offset += $xl; + } + + // construct the path + $url = str_repeat('..\\', $upLevelCount); + $url .= ($sz > 0) ? + $extendedFilePath : $shortenedFilePath; // use extended path if available + $url .= $hasText ? '#' : ''; + + break; + + + case 'UNC': + // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path + // todo: implement + return; + case 'workbook': // section 5.58.5: Hyperlink to the Current Workbook // e.g. Sheet2!B1:C2, stored in text mark field $url = 'sheet://'; break; - case 'local': - // section 5.58.2: Hyperlink containing a URL - // e.g. http://example.org/index.php - // todo: implement - - case 'UNC': - // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path - // todo: implement - default: return; @@ -3354,6 +3770,132 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } } + /** + * Read SHEETLAYOUT record. Stores sheet tab color information. + */ + private function _readSheetLayout() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // local pointer in record data + $offset = 0; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; repeated record identifier 0x0862 + + // offset: 2; size: 10; not used + + // offset: 12; size: 4; size of record data + // Excel 2003 uses size of 0x14 (documented), Excel 2007 uses size of 0x28 (not documented?) + $sz = $this->_GetInt4d($recordData, 12); + + switch ($sz) { + case 0x14: + // offset: 16; size: 2; color index for sheet tab + $colorIndex = $this->_GetInt2d($recordData, 16); + $color = $this->_readColor($colorIndex); + $this->_phpSheet->getTabColor()->setRGB($color['rgb']); + break; + + case 0x28: + // TODO: Investigate structure for .xls SHEETLAYOUT record as saved by MS Office Excel 2007 + return; + break; + } + } + } + + /** + * Read SHEETPROTECTION record + */ + private function _readSheetProtection() + { + $length = $this->_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; repeated record header + + // offset: 2; size: 9; not used + + // offset: 11; size: 8; unknown data + + // offset: 19; size: 2; option flags + $options = $this->_GetInt2d($recordData, 19); + + // bit: 0; mask 0x0001; 1 = user may edit objects, 0 = users must not edit objects + $bool = (0x0001 & $options) >> 0; + $this->_phpSheet->getProtection()->setObjects(!$bool); + + // bit: 1; mask 0x0002; edit scenarios + $bool = (0x0002 & $options) >> 1; + $this->_phpSheet->getProtection()->setScenarios(!$bool); + + // bit: 2; mask 0x0004; format cells + $bool = (0x0004 & $options) >> 2; + $this->_phpSheet->getProtection()->setFormatCells(!$bool); + + // bit: 3; mask 0x0008; format columns + $bool = (0x0008 & $options) >> 3; + $this->_phpSheet->getProtection()->setFormatColumns(!$bool); + + // bit: 4; mask 0x0010; format rows + $bool = (0x0010 & $options) >> 4; + $this->_phpSheet->getProtection()->setFormatRows(!$bool); + + // bit: 5; mask 0x0020; insert columns + $bool = (0x0020 & $options) >> 5; + $this->_phpSheet->getProtection()->setInsertColumns(!$bool); + + // bit: 6; mask 0x0040; insert rows + $bool = (0x0040 & $options) >> 6; + $this->_phpSheet->getProtection()->setInsertRows(!$bool); + + // bit: 7; mask 0x0080; insert hyperlinks + $bool = (0x0080 & $options) >> 7; + $this->_phpSheet->getProtection()->setInsertHyperlinks(!$bool); + + // bit: 8; mask 0x0100; delete columns + $bool = (0x0100 & $options) >> 8; + $this->_phpSheet->getProtection()->setDeleteColumns(!$bool); + + // bit: 9; mask 0x0200; delete rows + $bool = (0x0200 & $options) >> 9; + $this->_phpSheet->getProtection()->setDeleteRows(!$bool); + + // bit: 10; mask 0x0400; select locked cells + $bool = (0x0400 & $options) >> 10; + $this->_phpSheet->getProtection()->setSelectLockedCells(!$bool); + + // bit: 11; mask 0x0800; sort cell range + $bool = (0x0800 & $options) >> 11; + $this->_phpSheet->getProtection()->setSort(!$bool); + + // bit: 12; mask 0x1000; auto filter + $bool = (0x1000 & $options) >> 12; + $this->_phpSheet->getProtection()->setAutoFilter(!$bool); + + // bit: 13; mask 0x2000; pivot tables + $bool = (0x2000 & $options) >> 13; + $this->_phpSheet->getProtection()->setPivotTables(!$bool); + + // bit: 14; mask 0x4000; select unlocked cells + $bool = (0x4000 & $options) >> 14; + $this->_phpSheet->getProtection()->setSelectUnlockedCells(!$bool); + + // offset: 21; size: 2; not used + } + /** * Read RANGEPROTECTION record * Reading of this record is based on Microsoft Office Excel 97-2000 Binary File Format Specification, @@ -3523,9 +4065,10 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // dirty check to see if CONTINUE record could be a camouflaged MSODRAWING record // look inside CONTINUE record to see if it looks like a part of an Escher stream // we know that Escher stream may be split at least at + // 0xF003 MsofbtSpgrContainer // 0xF004 MsofbtSpContainer // 0xF00D MsofbtClientTextbox - $validSplitPoints = array(0xF004, 0xF00D); // add identifiers if we find more + $validSplitPoints = array(0xF003, 0xF004, 0xF00D); // add identifiers if we find more $splitPoint = $this->_GetInt2d($recordData, 2); if (in_array($splitPoint, $validSplitPoints)) { @@ -3772,6 +4315,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 'tRef3d': // 3d cell reference case 'tArea3d': // 3d cell range reference case 'tRefN': + case 'tAreaN': case 'tStr': // string $formulaStrings[] = "$space1$space0{$token['data']}"; unset($space0, $space1); @@ -4260,11 +4804,21 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $data = $this->_getFormulaFromData(substr($formulaData, 3, $subSize)); break; - case 0x4C: // Relative reference, used in shared formulas and some other places + case 0x2C: // Relative reference, used in shared formulas and some other places + case 0x4C: + case 0x6C: $name = 'tRefN'; $size = 5; $data = $this->_readBIFF8CellAddressB(substr($formulaData, 1, 4), $baseCell); break; + + case 0x2D: + case 0x4D: + case 0x6D: + $name = 'tAreaN'; + $size = 9; + $data = $this->_readBIFF8CellRangeAddressB(substr($formulaData, 1, 8), $baseCell); + break; case 0x3A: // 3d reference to cell case 0x5A: @@ -4504,6 +5058,88 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader return "$fc$fr:$lc$lr"; } + /** + * Reads a cell range address in BIFF8 for shared formulas. Uses positive and negative values for row and column + * to indicate offsets from a base cell + * section 3.3.4 + * + * @param string $subData + * @param string $baseCell Base cell + * @return string Cell range address + */ + private function _readBIFF8CellRangeAddressB($subData, $baseCell = 'A1') + { + list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); + $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; + + // TODO: if cell range is just a single cell, should this funciton + // not just return e.g. 'A1' and not 'A1:A1' ? + + // offset: 0; size: 2; first row + $frIndex = $this->_GetInt2d($subData, 0); // adjust below + + // offset: 2; size: 2; relative index to first row (0... 65535) should be treated as offset (-32768... 32767) + $lrIndex = $this->_GetInt2d($subData, 2); // adjust below + + // offset: 4; size: 2; first column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $fcIndex = 0x00FF & $this->_GetInt2d($subData, 4); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & $this->_GetInt2d($subData, 4))) { + // absolute column index + $fc = PHPExcel_Cell::stringFromColumnIndex($fcIndex); + $fc = '$' . $fc; + } else { + // column offset + $fcIndex = ($fcIndex <= 127) ? $fcIndex : $fcIndex - 256; + $fc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $fcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & $this->_GetInt2d($subData, 4))) { + // absolute row index + $fr = $frIndex + 1; + $fr = '$' . $fr; + } else { + // row offset + $frIndex = ($frIndex <= 32767) ? $frIndex : $frIndex - 65536; + $fr = $baseRow + $frIndex; + } + + // offset: 6; size: 2; last column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $lcIndex = 0x00FF & $this->_GetInt2d($subData, 6); + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & $this->_GetInt2d($subData, 6))) { + // absolute column index + $lc = PHPExcel_Cell::stringFromColumnIndex($lcIndex); + $lc = '$' . $lc; + } else { + // column offset + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & $this->_GetInt2d($subData, 6))) { + // absolute row index + $lr = $lrIndex + 1; + $lr = '$' . $lr; + } else { + // row offset + $lrIndex = ($lrIndex <= 32767) ? $lrIndex : $lrIndex - 65536; + $lr = $baseRow + $lrIndex; + } + + return "$fc$fr:$lc$lr"; + } + /** * Read BIFF8 cell range address list * section 2.5.15 @@ -4531,6 +5167,33 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader ); } + /** + * Read BIFF5 cell range address list + * section 2.5.15 + * + * @param string $subData + * @return array + */ + private function _readBIFF5CellRangeAddressList($subData) + { + $cellRangeAddresses = array(); + + // offset: 0; size: 2; number of the following cell range addresses + $nm = $this->_GetInt2d($subData, 0); + + $offset = 2; + // offset: 2; size: 6 * $nm; list of $nm (fixed) cell range addresses + for ($i = 0; $i < $nm; ++$i) { + $cellRangeAddresses[] = $this->_readBIFF5CellRangeAddressFixed(substr($subData, $offset, 6)); + $offset += 6; + } + + return array( + 'size' => 2 + 6 * $nm, + 'cellRangeAddresses' => $cellRangeAddresses, + ); + } + /** * Get a sheet range like Sheet1:Sheet3 from REF index * Note: If there is only one sheet in the range, one gets e.g Sheet1 diff --git a/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php b/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php index 3cdc38449..fd9f138ed 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Excel5/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ @@ -62,7 +62,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer/S * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel5_Escher { diff --git a/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php b/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php index a173b3f0f..c81297176 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php +++ b/libraries/PHPExcel/PHPExcel/Reader/IReadFilter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Reader_IReadFilter { diff --git a/libraries/PHPExcel/PHPExcel/Reader/IReader.php b/libraries/PHPExcel/PHPExcel/Reader/IReader.php index df758e0d1..52e0c2e89 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/IReader.php +++ b/libraries/PHPExcel/PHPExcel/Reader/IReader.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Reader_IReader { diff --git a/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php b/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php new file mode 100644 index 000000000..618a1f2d4 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Reader/OOCalc.php @@ -0,0 +1,500 @@ +_readDataOnly; + } + + /** + * Set read data only + * + * @param boolean $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadDataOnly($pValue = false) { + $this->_readDataOnly = $pValue; + return $this; + } + + /** + * Get which sheets to load + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } + + /** + * Set which sheets to load + * + * @param mixed $value + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadSheetsOnly($value = null) + { + $this->_loadSheetsOnly = is_array($value) ? + $value : array($value); + return $this; + } + + /** + * Set all sheets to load + * + * @return PHPExcel_Reader_Excel2007 + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = null; + return $this; + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_Excel2007 + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } + + /** + * Create a new PHPExcel_Reader_OOCalc + */ + public function __construct() { + $this->_sheetIndex = 0; + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFileName + * @return boolean + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Load file + $zip = new ZipArchive; + if ($zip->open($pFilename) === true) { + // check if it is an OOXML archive + $mimeType = $zip->getFromName("mimetype"); + + $zip->close(); + + return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet'); + } + + return false; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @throws Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $zip = new ZipArchive; + if ($zip->open($pFilename) === true) { +// echo '

Meta Information

'; + $xml = simplexml_load_string($zip->getFromName("meta.xml")); + $namespacesMeta = $xml->getNamespaces(true); +// echo '
';
+//			print_r($namespacesMeta);
+//			echo '

'; + + $docProps = $objPHPExcel->getProperties(); + $officeProperty = $xml->children($namespacesMeta['office']); + foreach($officeProperty as $officePropertyData) { + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { +// echo $propertyName.' = '.$propertyValue.'
'; + + switch ($propertyName) { + case 'title' : + $docProps->setTitle($propertyValue); + break; + case 'subject' : + $docProps->setSubject($propertyValue); + break; + case 'creator' : + $docProps->setCreator($propertyValue); + break; + case 'date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'description' : + $docProps->setDescription($propertyValue); + break; + } + } + $officePropertyMeta = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); + +// echo $propertyName.' = '.$propertyValue.'
'; +// foreach ($propertyValueAttributes as $key => $value) { +// echo $key.' = '.$value.'
'; +// } +// echo '
'; +// + switch ($propertyName) { + case 'keyword' : + $docProps->setKeywords($propertyValue); + break; + } + } + } + + +// echo '

Workbook Content

'; + $xml = simplexml_load_string($zip->getFromName("content.xml")); + $namespacesContent = $xml->getNamespaces(true); +// echo '
';
+//			print_r($namespacesContent);
+//			echo '

'; + + $workbook = $xml->children($namespacesContent['office']); + foreach($workbook->body->spreadsheet as $workbookData) { + $workbookData = $workbookData->children($namespacesContent['table']); + $worksheetID = 0; + foreach($workbookData->table as $worksheetDataSet) { + $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// print_r($worksheetData); +// echo '
'; + $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// print_r($worksheetDataAttributes); +// echo '
'; + if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && + (!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) { + continue; + } + +// echo '

Worksheet '.$worksheetDataAttributes['name'].'

'; + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheetDataAttributes['name'])) { + $worksheetName = $worksheetDataAttributes['name']; + $objPHPExcel->getActiveSheet()->setTitle($worksheetName); + } + + $rowID = 1; + foreach($worksheetData as $key => $rowData) { +// echo ''.$key.'
'; + switch ($key) { + case 'table-row' : + $columnID = 'A'; + foreach($rowData as $key => $cellData) { +// echo ''.$columnID.$rowID.'
'; + $cellDataText = $cellData->children($namespacesContent['text']); + $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); + $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); + +// echo 'Office Attributes: '; +// print_r($cellDataOfficeAttributes); +// echo '
Table Attributes: '; +// print_r($cellDataTableAttributes); +// echo '
Cell Data Text'; +// print_r($cellDataText); +// echo '
'; +// + $type = $formatting = $hyperlink = null; + $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cellDataTableAttributes['formula'])) { + $cellDataFormula = $cellDataTableAttributes['formula']; + $hasCalculatedValue = true; + } + + if (isset($cellDataText->p)) { +// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'
'; + switch ($cellDataOfficeAttributes['value-type']) { + case 'string' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + $dataValue = $cellDataText->p; + if (isset($dataValue->a)) { + $dataValue = $dataValue->a; + $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']); + $hyperlink = $cellXLinkAttributes['href']; + } + break; + case 'boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $dataValue = ($cellDataText->p == 'TRUE') ? True : False; + break; + case 'float' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; + } + break; + case 'date' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellDataOfficeAttributes['date-value'])); + if ($dataValue != floor($dataValue)) { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + } else { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15; + } + break; + case 'time' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS')))); + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + break; + } +// echo 'Data value is '.$dataValue.'
'; +// if (!is_null($hyperlink)) { +// echo 'Hyperlink is '.$hyperlink.'
'; +// } + } + + if ($hasCalculatedValue) { + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; +// echo 'Formula: '.$cellDataFormula.'
'; + $cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1); + $temp = explode('"',$cellDataFormula); + foreach($temp as $key => &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if (($key % 2) == 0) { + $value = preg_replace('/\[\.(.*):\.(.*)\]/Ui','$1:$2',$value); + $value = preg_replace('/\[\.(.*)\]/Ui','$1',$value); + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); +// echo 'Adjusted Formula: '.$cellDataFormula.'
'; + } + + if (!is_null($type)) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$dataValue.'
'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($dataValue); + } + if (($cellDataOfficeAttributes['value-type'] == 'date') || + ($cellDataOfficeAttributes['value-type'] == 'time')) { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rowID)->getNumberFormat()->setFormatCode($formatting); + } + if (!is_null($hyperlink)) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->getHyperlink()->setUrl($hyperlink); + } + } + + // Merged cells + if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { + $columnTo = $columnID; + if (isset($cellDataTableAttributes['number-columns-spanned'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); + } + $rowTo = $rowID; + if (isset($cellDataTableAttributes['number-rows-spanned'])) { + $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; + } + $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + + if (isset($cellDataTableAttributes['number-columns-repeated'])) { +// echo 'Repeated '.$cellDataTableAttributes['number-columns-repeated'].' times
'; + $columnID = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-repeated'] - 2); + } + ++$columnID; + } + ++$rowID; + break; + } + } + ++$worksheetID; + } + } + + } + + // Return + return $objPHPExcel; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_OOCalc + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Reader/SYLK.php b/libraries/PHPExcel/PHPExcel/Reader/SYLK.php new file mode 100644 index 000000000..a9bd64717 --- /dev/null +++ b/libraries/PHPExcel/PHPExcel/Reader/SYLK.php @@ -0,0 +1,506 @@ +_inputEncoding = 'ANSI'; + $this->_delimiter = ';'; + $this->_enclosure = '"'; + $this->_lineEnding = PHP_EOL; + $this->_sheetIndex = 0; + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFileName + * @return boolean + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Read sample data (first 2 KB will do) + $fh = fopen($pFilename, 'r'); + $data = fread($fh, 2048); + fclose($fh); + + // Count delimiters in file + $delimiterCount = substr_count($data, ';'); + if ($delimiterCount < 1) { + return false; + } + + // Analyze first line looking for ID; signature + $lines = explode("\n", $data); + if (substr($lines[0],0,4) != 'ID;P') { + return false; + } + + return true; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + } + + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'ANSI') + { + $this->_inputEncoding = $pValue; + } + + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @throws Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Create new PHPExcel + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); + } + $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex ); + + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); + + // Open file + $fileHandle = fopen($pFilename, 'r'); + if ($fileHandle === false) { + throw new Exception("Could not open file $pFilename for reading."); + } + + // Loop through file + $rowData = array(); + $column = $row = ''; + while (($rowData = fgets($fileHandle)) !== FALSE) { + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + $dataType = array_shift($rowData); + // Read shared styles + if ($dataType == 'P') { + $formatArray = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'P' : $formatArray['numberformat']['code'] = str_replace($fromFormats,$toFormats,substr($rowDatum,1)); + break; + case 'E' : + case 'F' : $formatArray['font']['name'] = substr($rowDatum,1); + break; + case 'L' : $formatArray['font']['size'] = substr($rowDatum,1); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i_formats['P'.$this->_format++] = $formatArray; + // Read cell value data + } elseif ($dataType == 'C') { + $hasCalculatedValue = false; + $cellData = $cellDataFormula = ''; + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'K' : $cellData = substr($rowDatum,1); + break; + case 'E' : $cellDataFormula = '='.substr($rowDatum,1); + // Convert R1C1 style references to A1 style references (but only when not quoted) + $temp = explode('"',$cellDataFormula); + foreach($temp as $key => &$value) { + // Only count/replace in alternate array entries + if (($key % 2) == 0) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $row; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $row + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $column; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $column + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); + $hasCalculatedValue = true; + break; + } + } + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + // Set cell value + $objPHPExcel->getActiveSheet()->setCellValue($columnLetter.$row, (($hasCalculatedValue) ? $cellDataFormula : $cellData)); + if ($hasCalculatedValue) { + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setCalculatedValue($cellData); + } + // Read cell formatting + } elseif ($dataType == 'F') { + $formatStyle = $columnWidth = $styleSettings = ''; + $styleData = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'P' : $formatStyle = $rowDatum; + break; + case 'W' : list($startCol,$endCol,$columnWidth) = explode(' ',substr($rowDatum,1)); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i '') && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]); + } + if ((count($styleData) > 0) && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($styleData); + } + if ($columnWidth > '') { + if ($startCol == $endCol) { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + } else { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $endCol = PHPExcel_Cell::stringFromColumnIndex($endCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + do { + $objPHPExcel->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth); + } while ($startCol != $endCol); + } + } + } else { + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + } + } + } + } + + // Close file + fclose($fileHandle); + + // Return + return $objPHPExcel; + } + + /** + * Get delimiter + * + * @return string + */ + public function getDelimiter() { + return $this->_delimiter; + } + + /** + * Set delimiter + * + * @param string $pValue Delimiter, defaults to , + * @return PHPExcel_Reader_SYLK + */ + public function setDelimiter($pValue = ',') { + $this->_delimiter = $pValue; + return $this; + } + + /** + * Get enclosure + * + * @return string + */ + public function getEnclosure() { + return $this->_enclosure; + } + + /** + * Set enclosure + * + * @param string $pValue Enclosure, defaults to " + * @return PHPExcel_Reader_SYLK + */ + public function setEnclosure($pValue = '"') { + if ($pValue == '') { + $pValue = '"'; + } + $this->_enclosure = $pValue; + return $this; + } + + /** + * Get line ending + * + * @return string + */ + public function getLineEnding() { + return $this->_lineEnding; + } + + /** + * Set line ending + * + * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) + * @return PHPExcel_Reader_SYLK + */ + public function setLineEnding($pValue = PHP_EOL) { + $this->_lineEnding = $pValue; + return $this; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_SYLK + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } +} diff --git a/libraries/PHPExcel/PHPExcel/Reader/Serialized.php b/libraries/PHPExcel/PHPExcel/Reader/Serialized.php index b95204ce8..120a6781c 100644 --- a/libraries/PHPExcel/PHPExcel/Reader/Serialized.php +++ b/libraries/PHPExcel/PHPExcel/Reader/Serialized.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Serialized implements PHPExcel_Reader_IReader { diff --git a/libraries/PHPExcel/PHPExcel/ReferenceHelper.php b/libraries/PHPExcel/PHPExcel/ReferenceHelper.php index 886ce286c..175bba122 100644 --- a/libraries/PHPExcel/PHPExcel/ReferenceHelper.php +++ b/libraries/PHPExcel/PHPExcel/ReferenceHelper.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.2, 2010-01-11 */ @@ -60,8 +60,8 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/FormulaToken.php'; * PHPExcel_ReferenceHelper (Singleton) * * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_ReferenceHelper { @@ -86,20 +86,20 @@ class PHPExcel_ReferenceHelper } /** - * Create a new PHPExcel_Calculation + * Create a new PHPExcel_ReferenceHelper */ protected function __construct() { } - /** - * Insert a new column, updating all possible related data - * - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @param int $pNumRows Number of rows to insert - * @throws Exception - */ - public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @param int $pNumRows Number of rows to insert + * @throws Exception + */ + public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { // Get a copy of the cell collection /*$aTemp = $pSheet->getCellCollection(); $aCellCollection = array(); @@ -108,15 +108,15 @@ class PHPExcel_ReferenceHelper }*/ $aCellCollection = $pSheet->getCellCollection(); - // Get coordinates of $pBefore - $beforeColumn = 'A'; - $beforeRow = 1; - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + // Get coordinates of $pBefore + $beforeColumn = 'A'; + $beforeRow = 1; + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); // Clear cells if we are removing columns or rows - $highestColumn = $pSheet->getHighestColumn(); - $highestRow = $pSheet->getHighestRow(); + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); // 1. Clear column strips if we are removing columns if ($pNumCols < 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols > 0) { @@ -155,7 +155,7 @@ class PHPExcel_ReferenceHelper // Should the cell be updated? Move value and cellXf index from one cell to another. if ( (PHPExcel_Cell::columnIndexFromString( $cell->getColumn() ) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)) && - ($cell->getRow() >= $beforeRow) + ($cell->getRow() >= $beforeRow) ) { // Update cell styles @@ -181,8 +181,8 @@ class PHPExcel_ReferenceHelper // Duplicate styles for the newly inserted cells - $highestColumn = $pSheet->getHighestColumn(); - $highestRow = $pSheet->getHighestRow(); + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); if ($pNumCols > 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 > 0) { for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { @@ -303,14 +303,13 @@ class PHPExcel_ReferenceHelper // Update worksheet: merge cells - $aMergeCells = array_reverse($pSheet->getMergeCells(), true); - foreach ($aMergeCells as $key => $value) { + $aMergeCells = $pSheet->getMergeCells(); + $aNewMergeCells = array(); // the new array of all merge cells + foreach ($aMergeCells as $key => &$value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->mergeCells( $newReference ); - $pSheet->unmergeCells( $key ); - } + $aNewMergeCells[$newReference] = $newReference; } + $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array // Update worksheet: protected cells @@ -365,57 +364,74 @@ class PHPExcel_ReferenceHelper // Garbage collect $pSheet->garbageCollect(); - } - - /** - * Update references within formulas - * - * @param string $pFormula Formula to update - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @param int $pNumRows Number of rows to insert - * @return string Updated formula - * @throws Exception - */ - public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - // Formula stack - $executableFormulaArray = array(); + } + /** + * Update references within formulas + * + * @param string $pFormula Formula to update + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @param int $pNumRows Number of rows to insert + * @return string Updated formula + * @throws Exception + */ + public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { // Parse formula into a tree of tokens $tokenisedFormula = PHPExcel_Calculation::getInstance()->parseFormula($pFormula); + $newCellTokens = $cellTokens = array(); + $adjustCount = 0; // Build the translation table of cell tokens foreach($tokenisedFormula as $token) { + $token = $token['value']; if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) { - $newCellTokens[] = $this->updateCellReference($token, $pBefore, $pNumCols, $pNumRows); - $cellTokens[] = '/'.$token.'/'; + list($column,$row) = PHPExcel_Cell::coordinateFromString($token); + // 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 + $column = PHPExcel_Cell::columnIndexFromString($column) + 100000; + $row += 10000000; + $cellIndex = $column.$row; + if (!isset($cellTokens[$cellIndex])) { + $newReference = $this->updateCellReference($token, $pBefore, $pNumCols, $pNumRows); + if ($newReference !== $token) { + $newCellTokens[$cellIndex] = preg_quote($newReference); + $cellTokens[$cellIndex] = '/(? $formulaBlock) { + foreach($formulaBlocks as $i => &$formulaBlock) { // Only count/replace in alternate array entries - if (($i++ % 2) == 0) { - $formulaBlocks[$formulaBlockKey] = preg_replace($cellTokens,$newCellTokens,$formulaBlock); + if (($i % 2) == 0) { + $formulaBlock = preg_replace($cellTokens,$newCellTokens,$formulaBlock); } } + unset($formulaBlock); + // Then rebuild the formula string return implode('"',$formulaBlocks); - } + } - /** - * Update cell reference - * - * @param string $pCellRange Cell range - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell range - * @throws Exception - */ - public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + /** + * Update cell reference + * + * @param string $pCellRange Cell range + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws Exception + */ + public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { // Is it in another worksheet? Will not have to update anything. if (strpos($pCellRange, "!") !== false) { return $pCellRange; @@ -423,24 +439,28 @@ class PHPExcel_ReferenceHelper } elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) { // Single cell return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows); - } else if (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { + } elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { // Range return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows); } else { // Return original return $pCellRange; } - } + } - /** - * Update named formulas (i.e. containing worksheet references / named ranges) - * - * @param PHPExcel $pPhpExcel Object to update - * @param string $oldName Old name (name to replace) - * @param string $newName New name - */ - public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { - foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { + /** + * Update named formulas (i.e. containing worksheet references / named ranges) + * + * @param PHPExcel $pPhpExcel Object to update + * @param string $oldName Old name (name to replace) + * @param string $newName New name + */ + public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { + if ($oldName == '') { + return; + } + + foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { foreach ($sheet->getCellCollection(false) as $cell) { if (!is_null($cell) && $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { $formula = $cell->getValue(); @@ -451,56 +471,56 @@ class PHPExcel_ReferenceHelper } } } - } - } + } + } - /** - * Update cell range - * - * @param string $pCellRange Cell range - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell range - * @throws Exception - */ - private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { + /** + * Update cell range + * + * @param string $pCellRange Cell range + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws Exception + */ + private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { // Update range $range = PHPExcel_Cell::splitRange($pCellRange); - for ($i = 0; $i < count($range); $i++) { - for ($j = 0; $j < count($range[$i]); $j++) { + for ($i = 0; $i < count($range); ++$i) { + for ($j = 0; $j < count($range[$i]); ++$j) { $range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows); } } // Recreate range string return PHPExcel_Cell::buildRange($range); - } else { - throw new Exception("Only cell ranges may be passed to this method."); - } - } + } else { + throw new Exception("Only cell ranges may be passed to this method."); + } + } - /** - * Update single cell reference - * - * @param string $pCellReference Single cell reference - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to increment - * @param int $pNumRows Number of rows to increment - * @return string Updated cell reference - * @throws Exception - */ - private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { - if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { - // Get coordinates of $pBefore - $beforeColumn = 'A'; - $beforeRow = 1; - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + /** + * Update single cell reference + * + * @param string $pCellReference Single cell reference + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell reference + * @throws Exception + */ + private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { + // Get coordinates of $pBefore + $beforeColumn = 'A'; + $beforeRow = 1; + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); // Get coordinates - $newColumn = 'A'; - $newRow = 1; + $newColumn = 'A'; + $newRow = 1; list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference ); // Make sure the reference can be used @@ -520,20 +540,20 @@ class PHPExcel_ReferenceHelper // Create new column reference if ($updateColumn) { - $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); + $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); } // Create new row reference if ($updateRow) { - $newRow = $newRow + $pNumRows; + $newRow = $newRow + $pNumRows; } // Return new reference return $newColumn . $newRow; - } else { - throw new Exception("Only single cell references may be passed to this method."); - } - } + } else { + throw new Exception("Only single cell references may be passed to this method."); + } + } /** * __clone implementation. Cloning should not be allowed in a Singleton! diff --git a/libraries/PHPExcel/PHPExcel/RichText.php b/libraries/PHPExcel/PHPExcel/RichText.php index ad78f112b..aca7796ea 100644 --- a/libraries/PHPExcel/PHPExcel/RichText.php +++ b/libraries/PHPExcel/PHPExcel/RichText.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -60,7 +60,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText implements PHPExcel_IComparable { @@ -157,7 +157,7 @@ class PHPExcel_RichText implements PHPExcel_IComparable // Return value $returnValue = ''; - // Loop trough all PHPExcel_RichText_ITextElement + // Loop through all PHPExcel_RichText_ITextElement foreach ($this->_richTextElements as $text) { $returnValue .= $text->getText(); } @@ -257,37 +257,6 @@ class PHPExcel_RichText implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php b/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php index 32948f79e..713a522c0 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php +++ b/libraries/PHPExcel/PHPExcel/RichText/ITextElement.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -41,7 +41,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_RichText_ITextElement { diff --git a/libraries/PHPExcel/PHPExcel/RichText/Run.php b/libraries/PHPExcel/PHPExcel/RichText/Run.php index e1297fcdd..82aff89c8 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/Run.php +++ b/libraries/PHPExcel/PHPExcel/RichText/Run.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -47,7 +47,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement { diff --git a/libraries/PHPExcel/PHPExcel/RichText/TextElement.php b/libraries/PHPExcel/PHPExcel/RichText/TextElement.php index 11b7cf120..d16a92995 100644 --- a/libraries/PHPExcel/PHPExcel/RichText/TextElement.php +++ b/libraries/PHPExcel/PHPExcel/RichText/TextElement.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -44,7 +44,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Date.php b/libraries/PHPExcel/PHPExcel/Shared/Date.php index f5e2ec8c2..dbb5be1eb 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Date.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Date.php @@ -3,7 +3,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,9 +21,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -47,7 +47,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Date { @@ -106,12 +106,15 @@ class PHPExcel_Shared_Date // Perform conversion if ($dateValue >= 1) { $utcDays = $dateValue - $myExcelBaseDate; - $returnValue = (integer) round($utcDays * 24 * 60 * 60); + $returnValue = round($utcDays * 24 * 60 * 60); + if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) { + $returnValue = (integer) $returnValue; + } } else { $hours = round($dateValue * 24); $mins = round($dateValue * 24 * 60) - round($hours * 60); $secs = round($dateValue * 24 * 60 * 60) - round($hours * 60 * 60) - round($mins * 60); - $returnValue = (integer) mktime($hours, $mins, $secs); + $returnValue = (integer) gmmktime($hours, $mins, $secs); } // Return @@ -132,8 +135,10 @@ class PHPExcel_Shared_Date $hours = round($time / 3600); $minutes = round($time / 60) - ($hours * 60); $seconds = round($time) - ($hours * 3600) - ($minutes * 60); + $dateObj = date_create('1-Jan-1970+'.$days.' days'); $dateObj->setTime($hours,$minutes,$seconds); + return $dateObj; } // function ExcelToPHPObject() diff --git a/libraries/PHPExcel/PHPExcel/Shared/Drawing.php b/libraries/PHPExcel/PHPExcel/Shared/Drawing.php index b56bbfd76..c2ad33df0 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,18 +20,30 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ +/** PHPExcel root */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); +} + +/** PHPExcel_Shared_String */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; + + /** * PHPExcel_Shared_Drawing * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Drawing { @@ -60,33 +72,67 @@ class PHPExcel_Shared_Drawing } /** - * Convert pixels to cell dimension. Exact algorithm not known. + * Convert pixels to column width. Exact algorithm not known. * By inspection of a real Excel file using Calibri 11, one finds 1000px ~ 142.85546875 * This gives a conversion factor of 7. Also, we assume that pixels and font size are proportional. * * @param int $pValue Value in pixels - * @param int $pFontSize Default font size of workbook + * @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook * @return int Value in cell dimension */ - public static function pixelsToCellDimension($pValue = 0, $pFontSize = 11) { - return $pValue * $pFontSize / 11 / 7; - } - - /** - * Convert cell width to pixels - * - * @param int $pValue Value in cell dimension - * @param int $pFontSize Default font size of workbook - * @return int Value in pixels - */ - public static function cellDimensionToPixels($pValue = 0, $pFontSize = 11) { - if ($pValue != 0) { - return $pValue * 7 * $pFontSize / 11; + public static function pixelsToCellDimension($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { + // Font name and size + $name = $pDefaultFont->getName(); + $size = $pDefaultFont->getSize(); + + if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { + // Exact width can be determined + $colWidth = $pValue + * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width'] + / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px']; } else { - return 0; + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $colWidth = $pValue * 11 + * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] + / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] / $size; } + + return $colWidth; } - + + /** + * Convert column width from (intrinsic) Excel units to pixels + * + * @param float $pValue Value in cell dimension + * @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook + * @return int Value in pixels + */ + public static function cellDimensionToPixels($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { + // Font name and size + $name = $pDefaultFont->getName(); + $size = $pDefaultFont->getSize(); + + if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { + // Exact width can be determined + $colWidth = $pValue + * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px'] + / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width']; + + } else { + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $colWidth = $pValue * $size + * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] + / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] / 11; + } + + // Round pixels to closest integer + $colWidth = (int) round($colWidth); + + return $colWidth; + } + /** * Convert pixels to points * diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher.php b/libraries/PHPExcel/PHPExcel/Shared/Escher.php index f0244eb60..4ed04b384 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php index 1084d94f6..243dab350 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php index 846b56990..8f07e52ae 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php index 481e7db55..952685307 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php index cdbdde01f..5883ae26b 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php index 4209b424c..c15995a63 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php index e472b218c..0ae494851 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php index d835a0687..87609cca7 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip { diff --git a/libraries/PHPExcel/PHPExcel/Shared/Excel5.php b/libraries/PHPExcel/PHPExcel/Shared/Excel5.php index b8e2050ee..f9b3f818a 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ @@ -39,12 +39,15 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; /** PHPExcel_Shared_Drawing */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; +/** PHPExcel_Shared_Font */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; + /** * PHPExcel_Shared_Excel5 * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Excel5 { @@ -59,8 +62,8 @@ class PHPExcel_Shared_Excel5 */ public static function sizeCol($sheet, $col = 'A') { - // default font size of workbook - $fontSize = $sheet->getParent()->getDefaultStyle()->getFont()->getSize(); + // default font of the workbook + $font = $sheet->getParent()->getDefaultStyle()->getFont(); $columnDimensions = $sheet->getColumnDimensions(); @@ -70,17 +73,19 @@ class PHPExcel_Shared_Excel5 // then we have column dimension with explicit width $columnDimension = $columnDimensions[$col]; $width = $columnDimension->getWidth(); - $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $fontSize); + $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); } else if ($sheet->getDefaultColumnDimension()->getWidth() != -1) { // then we have default column dimension with explicit width $defaultColumnDimension = $sheet->getDefaultColumnDimension(); $width = $defaultColumnDimension->getWidth(); - $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $fontSize); + $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); } else { - $pixelWidth = (int) 64 * $fontSize / 11; // here we interpolate from Calibri 11 + + // we don't even have any default column dimension. Width depends on default font + $pixelWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($font, true); } // now find the effective column width in pixels @@ -104,6 +109,9 @@ class PHPExcel_Shared_Excel5 */ public static function sizeRow($sheet, $row = 1) { + // default font of the workbook + $font = $sheet->getParent()->getDefaultStyle()->getFont(); + $rowDimensions = $sheet->getRowDimensions(); // first find the true row height in pixels (uncollapsed and unhidden) @@ -122,7 +130,11 @@ class PHPExcel_Shared_Excel5 $pixelRowHeight = PHPExcel_Shared_Drawing::pointsToPixels($rowHeight); } else { - $pixelRowHeight = 20; // here we assume Calibri 11 + + // we don't even have any default row dimension. Height depends on default font + $pointRowHeight = PHPExcel_Shared_Font::getDefaultRowHeightByFont($font); + $pixelRowHeight = PHPExcel_Shared_Font::fontSizeToPixels($pointRowHeight); + } // now find the effective row height in pixels @@ -301,8 +313,8 @@ class PHPExcel_Shared_Excel5 // Convert the pixel values to the percentage value expected by Excel $x1 = $x1 / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024; $y1 = $y1 / self::sizeRow($sheet, $row_start + 1) * 256; - $x2 = $width / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object - $y2 = $height / self::sizeRow($sheet, $row_end + 1) * 256; // Distance to bottom of object + $x2 = ($width + 1) / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object + $y2 = ($height + 1) / self::sizeRow($sheet, $row_end + 1) * 256; // Distance to bottom of object $startCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_start) . ($row_start + 1); $endCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_end) . ($row_end + 1); diff --git a/libraries/PHPExcel/PHPExcel/Shared/File.php b/libraries/PHPExcel/PHPExcel/Shared/File.php index 3c24520a9..a742d152f 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/File.php +++ b/libraries/PHPExcel/PHPExcel/Shared/File.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_File { @@ -79,7 +79,7 @@ class PHPExcel_Shared_File // Found something? if ($returnValue == '' || is_null($returnValue)) { - $pathArray = split('/' , $pFilename); + $pathArray = explode('/' , $pFilename); while(in_array('..', $pathArray) && $pathArray[0] != '..') { for ($i = 0; $i < count($pathArray); ++$i) { if ($pathArray[$i] == '..' && $i > 0) { @@ -95,4 +95,42 @@ class PHPExcel_Shared_File // Return return $returnValue; } + + /** + * Get the systems temporary directory. + * + * @return string + */ + public static function sys_get_temp_dir() + { + // sys_get_temp_dir is only available since PHP 5.2.1 + // http://php.net/manual/en/function.sys-get-temp-dir.php#94119 + + if ( !function_exists('sys_get_temp_dir')) { + if( $temp = getenv('TMP') ) { + return realpath($temp); + } + if( $temp = getenv('TEMP') ) { + return realpath($temp); + } + if( $temp = getenv('TMPDIR') ) { + return realpath($temp); + } + + // trick for creating a file in system's temporary dir + // without knowing the path of the system's temporary dir + $temp = tempnam(__FILE__, ''); + if (file_exists($temp)) { + unlink($temp); + return realpath(dirname($temp)); + } + + return null; + + } + + // use ordinary built-in PHP function + return realpath(sys_get_temp_dir()); + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/Font.php b/libraries/PHPExcel/PHPExcel/Shared/Font.php index 9bc8484fa..8bf67d5b3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/Font.php +++ b/libraries/PHPExcel/PHPExcel/Shared/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,21 +20,37 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ +/** PHPExcel root */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); +} + +/** PHPExcel_Shared_String */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; + + /** * PHPExcel_Shared_Font * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Font { + /* Methods for resolving autosize value */ + const AUTOSIZE_METHOD_APPROX = 'approx'; + const AUTOSIZE_METHOD_EXACT = 'exact'; + /** Character set codes used by BIFF5-8 in Font records */ const CHARSET_ANSI_LATIN = 0x00; const CHARSET_SYSTEM_DEFAULT = 0x01; @@ -56,6 +72,175 @@ class PHPExcel_Shared_Font const CHARSET_ANSI_LATIN_II = 0xEE; const CHARSET_OEM_LATIN_I = 0xFF; + // XXX: Constants created! + /** Font filenames */ + const ARIAL = 'arial.ttf'; + const ARIAL_BOLD = 'arialbd.ttf'; + const ARIAL_ITALIC = 'ariali.ttf'; + const ARIAL_BOLD_ITALIC = 'arialbi.ttf'; + + const CALIBRI = 'CALIBRI.TTF'; + const CALIBRI_BOLD = 'CALIBRIB.TTF'; + const CALIBRI_ITALIC = 'CALIBRII.TTF'; + const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF'; + + const COMIC_SANS_MS = 'comic.ttf'; + const COMIC_SANS_MS_BOLD = 'comicbd.ttf'; + + const COURIER_NEW = 'cour.ttf'; + const COURIER_NEW_BOLD = 'courbd.ttf'; + const COURIER_NEW_ITALIC = 'couri.ttf'; + const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf'; + + const GEORGIA = 'georgia.ttf'; + const GEORGIA_BOLD = 'georgiab.ttf'; + const GEORGIA_ITALIC = 'georgiai.ttf'; + const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf'; + + const IMPACT = 'impact.ttf'; + + const LIBERATION_SANS = 'LiberationSans-Regular.ttf'; + const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf'; + const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf'; + const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf'; + + const LUCIDA_CONSOLE = 'lucon.ttf'; + const LUCIDA_SANS_UNICODE = 'l_10646.ttf'; + + const MICROSOFT_SANS_SERIF = 'micross.ttf'; + + const PALATINO_LINOTYPE = 'pala.ttf'; + const PALATINO_LINOTYPE_BOLD = 'palab.ttf'; + const PALATINO_LINOTYPE_ITALIC = 'palai.ttf'; + const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf'; + + const SYMBOL = 'symbol.ttf'; + + const TAHOMA = 'tahoma.ttf'; + const TAHOMA_BOLD = 'tahomabd.ttf'; + + const TIMES_NEW_ROMAN = 'times.ttf'; + const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf'; + const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf'; + const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf'; + + const TREBUCHET_MS = 'trebuc.ttf'; + const TREBUCHET_MS_BOLD = 'trebucbd.ttf'; + const TREBUCHET_MS_ITALIC = 'trebucit.ttf'; + const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf'; + + const VERDANA = 'verdana.ttf'; + const VERDANA_BOLD = 'verdanab.ttf'; + const VERDANA_ITALIC = 'verdanai.ttf'; + const VERDANA_BOLD_ITALIC = 'verdanaz.ttf'; + + /** + * AutoSize method + * + * @var string + */ + private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX; + + /** + * Path to folder containing TrueType font .ttf files + * + * @var string + */ + private static $trueTypeFontPath = null; + + /** + * How wide is a default column for a given default font and size? + * Empirical data found by inspecting real Excel files and reading off the pixel width + * in Microsoft Office Excel 2007. + * + * @var array + */ + public static $defaultColumnWidths = array( + 'Arial' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 56, 'width' => 9.33203125), + 9 => array('px' => 64, 'width' => 9.14062500), + 10 => array('px' => 64, 'width' => 9.14062500), + ), + 'Calibri' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 56, 'width' => 9.33203125), + 9 => array('px' => 56, 'width' => 9.33203125), + 10 => array('px' => 64, 'width' => 9.14062500), + 11 => array('px' => 64, 'width' => 9.14062500), + ), + 'Verdana' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 64, 'width' => 9.14062500), + 9 => array('px' => 72, 'width' => 9.00000000), + 10 => array('px' => 72, 'width' => 9.00000000), + ), + ); + + /** + * Set autoSize method + * + * @param string $pValue + */ + public static function setAutoSizeMethod($pValue = 'approx') + { + self::$autoSizeMethod = $pValue; + } + + /** + * Get autoSize method + * + * @return string + */ + public static function getAutoSizeMethod() + { + return self::$autoSizeMethod; + } + + /** + * Set the path to the folder containing .ttf files. There should be a trailing slash. + * Typical locations on variout some platforms: + *
    + *
  • C:/Windows/Fonts/
  • + *
  • /usr/share/fonts/truetype/
  • + *
  • ~/.fonts/
  • + *
+ * + * @param string $pValue + */ + public static function setTrueTypeFontPath($pValue = '') + { + self::$trueTypeFontPath = $pValue; + } + + /** + * Get the path to the folder containing .ttf files. + * + * @return string + */ + public static function getTrueTypeFontPath() + { + return self::$trueTypeFontPath; + } + /** * Calculate an (approximate) OpenXML column width, based on font size and text contained * @@ -65,29 +250,120 @@ class PHPExcel_Shared_Font * @param int $rotation Rotation angle * @return int Column width */ - public static function calculateColumnWidth($fontSize = 9, $fontSizeInPixels = false, $columnText = '', $rotation = 0) { - if (!$fontSizeInPixels) { - // Translate points size to pixel size - $fontSize = PHPExcel_Shared_Font::fontSizeToPixels($fontSize); - } - - // If it is rich text, use rich text... + public static function calculateColumnWidth(PHPExcel_Style_Font $font, $columnText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) { + + // If it is rich text, use plain text if ($columnText instanceof PHPExcel_RichText) { $columnText = $columnText->getPlainText(); } - - // Only measure the part before the first newline character - if (strpos($columnText, "\r") !== false) { - $columnText = substr($columnText, 0, strpos($columnText, "\r")); - } + + // Only measure the part before the first newline character (is always "\n") if (strpos($columnText, "\n") !== false) { $columnText = substr($columnText, 0, strpos($columnText, "\n")); } + + // Try to get the exact text width in pixels + try { + // If autosize method is set to 'approx', use approximation + if (self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX) { + throw new Exception('AutoSize method is set to approx'); + } + + // Width of text in pixels excl. padding + $columnWidth = self::getTextWidthPixelsExact($columnText, $font, $rotation); + + // Excel adds some padding, use 1.07 of the width of an 'n' glyph + $columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07); // pixels incl. padding + + } catch (Exception $e) { + // Width of text in pixels excl. padding, approximation + $columnWidth = self::getTextWidthPixelsApprox($columnText, $font, $rotation); + + // Excel adds some padding, just use approx width of 'n' glyph + $columnWidth += self::getTextWidthPixelsApprox('n', $font, 0); + } + + // Convert from pixel width to column width + $columnWidth = PHPExcel_Shared_Drawing::pixelsToCellDimension($columnWidth, $defaultFont); + + // Return + return round($columnWidth, 6); + } + + /** + * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle + * + * @param string $text + * @param PHPExcel_Style_Font + * @param int $rotation + * @return int + * @throws Exception + */ + public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) { + if (!function_exists('imagettfbbox')) { + throw new Exception('GD library needs to be enabled'); + } + + // font size should really be supplied in pixels in GD2, + // but since GD2 seems to assume 72dpi, pixels and points are the same + $fontFile = self::getTrueTypeFontFileFromFont($font); + $textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text); + + // Get corners positions + $lowerLeftCornerX = $textBox[0]; + $lowerLeftCornerY = $textBox[1]; + $lowerRightCornerX = $textBox[2]; + $lowerRightCornerY = $textBox[3]; + $upperRightCornerX = $textBox[4]; + $upperRightCornerY = $textBox[5]; + $upperLeftCornerX = $textBox[6]; + $upperLeftCornerY = $textBox[7]; - // Calculate column width - // values 1.025 and 0.584 found via interpolation by inspecting real Excel files with - // Calibri font. May need further adjustment - $columnWidth = 1.025 * strlen($columnText) + 0.584; // Excel adds some padding + // Consider the rotation when calculating the width + $textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); + + return $textWidth; + } + + /** + * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle + * + * @param string $columnText + * @param PHPExcel_Style_Font $font + * @param int $rotation + * @return int Text width in pixels (no padding added) + */ + public static function getTextWidthPixelsApprox($columnText, PHPExcel_Style_Font $font = null, $rotation = 0) + { + $fontName = $font->getName(); + $fontSize = $font->getSize(); + + // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. + switch ($fontName) { + case 'Calibri': + // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. + $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size + break; + + case 'Arial': + // value 7 was found via interpolation by inspecting real Excel files with Arial 10 font. + $columnWidth = (int) (7 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size + break; + + case 'Verdana': + // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. + $columnWidth = (int) (8 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size + break; + + default: + // just assume Calibri + $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size + break; + } // Calculate approximate rotated column width if ($rotation !== 0) { @@ -101,18 +377,19 @@ class PHPExcel_Shared_Font } } - // Return - return round($columnWidth, 6); + // pixel width is an integer + $columnWidth = (int) $columnWidth; + return $columnWidth; } - + /** * Calculate an (approximate) pixel size, based on a font points size * * @param int $fontSizeInPoints Font size (in points) * @return int Font size (in pixels) */ - public static function fontSizeToPixels($fontSizeInPoints = 12) { - return ((16 / 12) * $fontSizeInPoints); + public static function fontSizeToPixels($fontSizeInPoints = 11) { + return (int) ((4 / 3) * $fontSizeInPoints); } /** @@ -135,6 +412,133 @@ class PHPExcel_Shared_Font return ($sizeInCm * 37.795275591); } + /** + * Returns the font path given the font + * + * @param PHPExcel_Style_Font + * @return string Path to TrueType font file + */ + public static function getTrueTypeFontFileFromFont($font) { + if (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)) { + throw new Exception('Valid directory to TrueType Font files not specified'); + } + + $name = $font->getName(); + $bold = $font->getBold(); + $italic = $font->getItalic(); + + // Check if we can map font to true type font file + switch ($name) { + case 'Arial': + $fontFile = ( + $bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD) + : ($italic ? self::ARIAL_ITALIC : self::ARIAL) + ); + break; + + case 'Calibri': + $fontFile = ( + $bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD) + : ($italic ? self::CALIBRI_ITALIC : self::CALIBRI) + ); + break; + + case 'Courier New': + $fontFile = ( + $bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD) + : ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW) + ); + break; + + case 'Comic Sans MS': + $fontFile = ( + $bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS + ); + break; + + case 'Georgia': + $fontFile = ( + $bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD) + : ($italic ? self::GEORGIA_ITALIC : self::GEORGIA) + ); + break; + + case 'Impact': + $fontFile = self::IMPACT; + break; + + case 'Liberation Sans': + $fontFile = ( + $bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD) + : ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS) + ); + break; + + case 'Lucida Console': + $fontFile = self::LUCIDA_CONSOLE; + break; + + case 'Lucida Sans Unicode': + $fontFile = self::LUCIDA_SANS_UNICODE; + break; + + case 'Microsoft Sans Serif': + $fontFile = self::MICROSOFT_SANS_SERIF; + break; + + case 'Palatino Linotype': + $fontFile = ( + $bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD) + : ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE) + ); + break; + + case 'Symbol': + $fontFile = self::SYMBOL; + break; + + case 'Tahoma': + $fontFile = ( + $bold ? self::TAHOMA_BOLD : self::TAHOMA + ); + break; + + case 'Times New Roman': + $fontFile = ( + $bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD) + : ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN) + ); + break; + + case 'Trebuchet MS': + $fontFile = ( + $bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD) + : ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS) + ); + break; + + case 'Verdana': + $fontFile = ( + $bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD) + : ($italic ? self::VERDANA_ITALIC : self::VERDANA) + ); + break; + + default: + throw new Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file'); + break; + } + + $fontFile = self::$trueTypeFontPath . $fontFile; + + // Check if file actually exists + if (!file_exists($fontFile)) { + throw New Exception('TrueType Font file not found'); + } + + return $fontFile; + } + /** * Returns the associated charset for the font name. * @@ -145,6 +549,7 @@ class PHPExcel_Shared_Font { switch ($name) { // Add more cases. Check FONT records in real Excel files. + case 'EucrosiaUPC': return self::CHARSET_ANSI_THAI; case 'Wingdings': return self::CHARSET_SYMBOL; case 'Wingdings 2': return self::CHARSET_SYMBOL; case 'Wingdings 3': return self::CHARSET_SYMBOL; @@ -152,4 +557,214 @@ class PHPExcel_Shared_Font } } + /** + * Get the effective column width for columns without a column dimension or column with width -1 + * For example, for Calibri 11 this is 9.140625 (64 px) + * + * @param PHPExcel_Style_Font $font The workbooks default font + * @param boolean $pPixels true = return column width in pixels, false = return in OOXML units + * @return mixed Column width + */ + public static function getDefaultColumnWidthByFont(PHPExcel_Style_Font $font, $pPixels = false) + { + if (isset(self::$defaultColumnWidths[$font->getName()][$font->getSize()])) { + // Exact width can be determined + $columnWidth = $pPixels ? + self::$defaultColumnWidths[$font->getName()][$font->getSize()]['px'] + : self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width']; + + } else { + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $columnWidth = $pPixels ? + self::$defaultColumnWidths['Calibri'][11]['px'] + : self::$defaultColumnWidths['Calibri'][11]['width']; + $columnWidth = $columnWidth * $font->getSize() / 11; + + // Round pixels to closest integer + if ($pPixels) { + $columnWidth = (int) round($columnWidth); + } + } + + return $columnWidth; + } + + /** + * Get the effective row height for rows without a row dimension or rows with height -1 + * For example, for Calibri 11 this is 15 points + * + * @param PHPExcel_Style_Font $font The workbooks default font + * @return float Row height in points + */ + public static function getDefaultRowHeightByFont(PHPExcel_Style_Font $font) + { + switch ($font->getName()) { + case 'Arial': + switch ($font->getSize()) { + case 10: + // inspection of Arial 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Arial 9 workbook says 12.00pt ~16px + $rowHeight = 12; + break; + + case 8: + // inspection of Arial 8 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 7: + // inspection of Arial 7 workbook says 9.00pt ~12px + $rowHeight = 9; + break; + + case 6: + case 5: + // inspection of Arial 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Arial 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Arial 3 workbook says 6.00pt ~8px + $rowHeight = 6; + break; + + case 2: + case 1: + // inspection of Arial 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Arial 10 workbook as an approximation, extrapolation + $rowHeight = 12.75 * $font->getSize() / 10; + break; + } + break; + + case 'Calibri': + switch ($font->getSize()) { + case 11: + // inspection of Calibri 11 workbook says 15.00pt ~20px + $rowHeight = 15; + break; + + case 10: + // inspection of Calibri 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Calibri 9 workbook says 12.00pt ~16px + $rowHeight = 12; + break; + + case 8: + // inspection of Calibri 8 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 7: + // inspection of Calibri 7 workbook says 9.00pt ~12px + $rowHeight = 9; + break; + + case 6: + case 5: + // inspection of Calibri 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Calibri 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Calibri 3 workbook says 6.00pt ~8px + $rowHeight = 6.00; + break; + + case 2: + case 1: + // inspection of Calibri 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Calibri 11 workbook as an approximation, extrapolation + $rowHeight = 15 * $font->getSize() / 11; + break; + } + break; + + case 'Verdana': + switch ($font->getSize()) { + case 10: + // inspection of Verdana 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Verdana 9 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 8: + // inspection of Verdana 8 workbook says 10.50pt ~14px + $rowHeight = 10.50; + break; + + case 7: + // inspection of Verdana 7 workbook says 9.00pt ~12px + $rowHeight = 9.00; + break; + + case 6: + case 5: + // inspection of Verdana 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Verdana 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Verdana 3 workbook says 6.00pt ~8px + $rowHeight = 6; + break; + + case 2: + case 1: + // inspection of Verdana 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Verdana 10 workbook as an approximation, extrapolation + $rowHeight = 12.75 * $font->getSize() / 10; + break; + } + break; + + default: + // just use Calibri as an approximation + $rowHeight = 15 * $font->getSize() / 11; + break; + } + + return $rowHeight; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php index efababbc4..49659d03c 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php +++ b/libraries/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php @@ -21,6 +21,8 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/LUDecomposition.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/QRDecomposition.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/EigenvalueDecomposition.php'; require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/SingularValueDecomposition.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; /* * Matrix class @@ -760,7 +762,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] += $M->get($i, $j); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] += $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; @@ -832,7 +848,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] -= $M->get($i, $j); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] -= $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; @@ -906,7 +936,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] *= $M->get($i, $j); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] *= $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; @@ -943,7 +987,26 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $M->set($i, $j, $this->A[$i][$j] / $M->get($i, $j)); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + if ($value == 0) { + // Trap for Divide by Zero error + $M->set($i, $j, '#DIV/0!'); + } else { + $M->set($i, $j, $this->A[$i][$j] / $value); + } + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $M; @@ -1181,7 +1244,21 @@ class Matrix { $this->checkMatrixDimensions($M); for($i = 0; $i < $this->m; ++$i) { for($j = 0; $j < $this->n; ++$j) { - $this->A[$i][$j] = pow($this->A[$i][$j],$M->get($i, $j)); + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] = pow($this->A[$i][$j],$value); + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } } } return $this; diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php index f9673f071..df96995c8 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (C) 2006 - 2009 PHPExcel + * Copyright (C) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_OLE * @copyright Copyright (c) 2006 - 2007 Christian Schmidt * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ /** PHPExcel root directory */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php b/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php index fd4bc947b..3cf1d1bd3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLE/OLE_Root.php @@ -248,7 +248,7 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS . pack("V", 0) . pack("V", 0x1000) . pack("V", $iSBDcnt ? 0 : -2) //Small Block Depot - . pack("V", 1) + . pack("V", $iSBDcnt) ); // Extra BDList Start, Count if ($iBdCnt < $i1stBdL) { diff --git a/libraries/PHPExcel/PHPExcel/Shared/OLERead.php b/libraries/PHPExcel/PHPExcel/Shared/OLERead.php index 6ccaab9b8..46cb5ade3 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/OLERead.php +++ b/libraries/PHPExcel/PHPExcel/Shared/OLERead.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); diff --git a/libraries/PHPExcel/PHPExcel/Shared/PDF.php b/libraries/PHPExcel/PHPExcel/Shared/PDF.php index 8d1416054..b66e8e0c1 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/PDF.php +++ b/libraries/PHPExcel/PHPExcel/Shared/PDF.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php b/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php index e8d11510b..1a5c11a33 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php +++ b/libraries/PHPExcel/PHPExcel/Shared/PasswordHasher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_PasswordHasher { diff --git a/libraries/PHPExcel/PHPExcel/Shared/String.php b/libraries/PHPExcel/PHPExcel/Shared/String.php index 8a105f014..e165fdd63 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/String.php +++ b/libraries/PHPExcel/PHPExcel/Shared/String.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,10 +31,16 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_String { + /** Constants */ + /** Regular Expressions */ + // Fraction + const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)'; + + /** * Control characters array * @@ -42,6 +48,20 @@ class PHPExcel_Shared_String */ private static $_controlCharacters = array(); + /** + * Decimal separator + * + * @var string + */ + private static $_decimalSeparator; + + /** + * Thousands separator + * + * @var string + */ + private static $_thousandsSeparator; + /** * Is mbstring extension avalable? * @@ -60,7 +80,7 @@ class PHPExcel_Shared_String * Build control characters array */ private static function _buildControlCharacters() { - for ($i = 0; $i <= 19; ++$i) { + for ($i = 0; $i <= 31; ++$i) { if ($i != 9 && $i != 10 && $i != 13) { $find = '_x' . sprintf('%04s' , strtoupper(dechex($i))) . '_'; $replace = chr($i); @@ -97,12 +117,19 @@ class PHPExcel_Shared_String return self::$_isIconvEnabled; } - // IBM AIX iconv() does not work - self::$_isIconvEnabled = function_exists('iconv') && - !(defined('PHP_OS') && @stristr(PHP_OS, 'AIX') && defined('ICONV_IMPL') - && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) && defined('ICONV_VERSION') - && (@strcasecmp(ICONV_VERSION, 'unknown') == 0)) ? - true : false; + // Check that iconv exists + // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false, + // we cannot use iconv when that happens + // Also, sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0 + // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773) + if (function_exists('iconv') + && @iconv('UTF-8', 'UTF-16LE', 'x') + && @iconv_substr('A', 0, 1, 'UTF-8') ) { + + self::$_isIconvEnabled = true; + } else { + self::$_isIconvEnabled = false; + } return self::$_isIconvEnabled; } @@ -172,7 +199,7 @@ class PHPExcel_Shared_String // else, no conversion return $value; } - + /** * Check if a string contains UTF8 data * @@ -213,7 +240,7 @@ class PHPExcel_Shared_String $ln = self::CountCharacters($value, 'UTF-8'); // option flags - $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? + $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? 0x0001 : 0x0000; // characters @@ -239,7 +266,7 @@ class PHPExcel_Shared_String $ln = self::CountCharacters($value, 'UTF-8'); // option flags - $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? + $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? 0x0001 : 0x0000; // characters @@ -272,7 +299,7 @@ class PHPExcel_Shared_String // else, no conversion return $value; } - + /** * Get character count. First try mbstring, then iconv, finally strlen * @@ -322,4 +349,82 @@ class PHPExcel_Shared_String return $string; } + + /** + * Identify whether a string contains a fractional numeric value, + * and convert it to a numeric if it is + * + * @param string &$operand string value to test + * @return boolean + */ + public static function convertToNumberIfFraction(&$operand) { + if (preg_match('/^'.self::STRING_REGEXP_FRACTION.'$/i', $operand, $match)) { + $sign = ($match[1] == '-') ? '-' : '+'; + $fractionFormula = '='.$sign.$match[2].$sign.$match[3]; + $operand = PHPExcel_Calculation::getInstance()->_calculateFormulaValue($fractionFormula); + return true; + } + return false; + } // function convertToNumberIfFraction() + + /** + * Get the decimal separator. If it has not yet been set explicitly, try to obtain number + * formatting information from locale. + * + * @return string + */ + public static function getDecimalSeparator() + { + if (!isset(self::$_decimalSeparator)) { + $localeconv = localeconv(); + self::$_decimalSeparator = $localeconv['decimal_point'] != '' + ? $localeconv['decimal_point'] : $localeconv['mon_decimal_point']; + + if (self::$_decimalSeparator == '') + { + // Default to . + self::$_decimalSeparator = '.'; + } + } + return self::$_decimalSeparator; + } + + /** + * Set the decimal separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() + * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF + * + * @param string $pValue Character for decimal separator + */ + public static function setDecimalSeparator($pValue = '.') + { + self::$_decimalSeparator = $pValue; + } + + /** + * Get the thousands separator. If it has not yet been set explicitly, try to obtain number + * formatting information from locale. + * + * @return string + */ + public static function getThousandsSeparator() + { + if (!isset(self::$_thousandsSeparator)) { + $localeconv = localeconv(); + self::$_thousandsSeparator = $localeconv['thousands_sep'] != '' + ? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep']; + } + return self::$_thousandsSeparator; + } + + /** + * Set the thousands separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() + * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF + * + * @param string $pValue Character for thousands separator + */ + public static function setThousandsSeparator($pValue = ',') + { + self::$_thousandsSeparator = $pValue; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php b/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php index 9600a731d..4cd3d726a 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php +++ b/libraries/PHPExcel/PHPExcel/Shared/XMLWriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ if (!defined('DATE_W3C')) { @@ -34,7 +34,7 @@ if (!defined('DATE_W3C')) { * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_XMLWriter { /** Temporary storage method */ diff --git a/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php b/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php index ebcfcb00f..b5bc1cb02 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php +++ b/libraries/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -35,7 +35,7 @@ PHPExcel_Shared_ZipStreamWrapper::register(); * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_ZipStreamWrapper { /** @@ -84,7 +84,7 @@ class PHPExcel_Shared_ZipStreamWrapper { } // Parse URL - $url = @parse_url($path); + $url = @parse_url(str_replace('zip://', 'file://', $path)); // Fix URL if (!is_array($url)) { diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php index 00791da84..bd96d5827 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Best_Fit { @@ -239,7 +239,11 @@ class PHPExcel_Best_Fit $this->_SSResiduals = $SSres; $this->_DFResiduals = $this->_valueCount - 1 - $const; - $this->_stdevOfResiduals = sqrt($SSres / $this->_DFResiduals); + if ($this->_DFResiduals == 0.0) { + $this->_stdevOfResiduals = 0.0; + } else { + $this->_stdevOfResiduals = sqrt($SSres / $this->_DFResiduals); + } if (($SStot == 0.0) || ($SSres == $SStot)) { $this->_goodnessOfFit = 1; } else { @@ -252,9 +256,17 @@ class PHPExcel_Best_Fit $this->_slopeSE = $this->_stdevOfResiduals / sqrt($SSsex); $this->_intersectSE = $this->_stdevOfResiduals * sqrt(1 / ($this->_valueCount - ($sumX * $sumX) / $sumX2)); if ($this->_SSResiduals != 0.0) { - $this->_F = $this->_SSRegression / ($this->_SSResiduals / $this->_DFResiduals); + if ($this->_DFResiduals == 0.0) { + $this->_F = 0.0; + } else { + $this->_F = $this->_SSRegression / ($this->_SSResiduals / $this->_DFResiduals); + } } else { - $this->_F = $this->_SSRegression / $this->_DFResiduals; + if ($this->_DFResiduals == 0.0) { + $this->_F = 0.0; + } else { + $this->_F = $this->_SSRegression / $this->_DFResiduals; + } } } // function _calculateGoodnessOfFit() diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php index 498c47050..1d7212d9d 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit { @@ -84,8 +84,14 @@ class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit private function _exponential_regression($yValues, $xValues, $const) { - $mArray = $xValues; - $yValues = array_map('log',$yValues); + foreach($yValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); $this->_leastSquareFit($yValues, $xValues, $const); } // function _exponential_regression() diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php index 2808fb4f3..265048196 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Linear_Best_Fit extends PHPExcel_Best_Fit { diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php index ba28dd833..115c78d0d 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit { @@ -68,8 +68,14 @@ class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit private function _logarithmic_regression($yValues, $xValues, $const) { - $mArray = $xValues; - $xValues = array_map('log',$xValues); + foreach($xValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); $this->_leastSquareFit($yValues, $xValues, $const); } // function _logarithmic_regression() diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php index 65b8eee69..dca14ff3c 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Polynomial_Best_Fit extends PHPExcel_Best_Fit { diff --git a/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php b/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php index 2a1b10c1f..651aec2fe 100644 --- a/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php +++ b/libraries/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -42,7 +42,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; * * @category PHPExcel * @package PHPExcel_Shared_Best_Fit - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit { @@ -76,10 +76,22 @@ class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit private function _power_regression($yValues, $xValues, $const) { - $mArray = $xValues; - sort($mArray,SORT_NUMERIC); - $xValues = array_map('log',$xValues); - $yValues = array_map('log',$yValues); + foreach($xValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); + foreach($yValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); $this->_leastSquareFit($yValues, $xValues, $const); } // function _power_regression() diff --git a/libraries/PHPExcel/PHPExcel/Style.php b/libraries/PHPExcel/PHPExcel/Style.php index 874747749..5636df48f 100644 --- a/libraries/PHPExcel/PHPExcel/Style.php +++ b/libraries/PHPExcel/PHPExcel/Style.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -66,7 +66,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style implements PHPExcel_IComparable { @@ -201,7 +201,7 @@ class PHPExcel_Style implements PHPExcel_IComparable public function getSharedComponent() { $activeSheet = $this->getActiveSheet(); - $selectedCell = $this->getXActiveCell(); // e.g. 'A1' + $selectedCell = $this->getActiveCell(); // e.g. 'A1' if ($activeSheet->cellExists($selectedCell)) { $cell = $activeSheet->getCell($selectedCell); @@ -230,9 +230,9 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->_parent->getActiveSheet()->getXSelectedCells(); + return $this->_parent->getActiveSheet()->getSelectedCells(); } /** @@ -241,9 +241,9 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->_parent->getActiveSheet()->getXActiveCell(); + return $this->_parent->getActiveSheet()->getActiveCell(); } /** @@ -299,204 +299,253 @@ class PHPExcel_Style implements PHPExcel_IComparable if (is_array($pStyles)) { if ($this->_isSupervisor) { - $pRange = $this->getXSelectedCells(); + $pRange = $this->getSelectedCells(); - if (is_array($pStyles)) { - // Uppercase coordinate - $pRange = strtoupper($pRange); - - // Is it a cell range or a single cell? - $rangeA = ''; - $rangeB = ''; - if (strpos($pRange, ':') === false) { - $rangeA = $pRange; - $rangeB = $pRange; - } else { - list($rangeA, $rangeB) = explode(':', $pRange); - } - - // Calculate range outer borders - $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); - $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); - - // Translate column into index - $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; - $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; - - // Make sure we can loop upwards on rows and columns - if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { - $tmp = $rangeStart; - $rangeStart = $rangeEnd; - $rangeEnd = $tmp; - } - - // Advanced mode - if ($pAdvanced && isset($pStyles['borders'])) { - - // 'allborders' is a shorthand property for 'outline' and 'inside' and - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['allborders'])) { - foreach (array('outline', 'inside') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['allborders']; - } - } - unset($pStyles['borders']['allborders']); // not needed any more - } - - // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['outline'])) { - foreach (array('top', 'right', 'bottom', 'left') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['outline']; - } - } - unset($pStyles['borders']['outline']); // not needed any more - } - - // 'inside' is a shorthand property for 'vertical' and 'horizontal' - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['inside'])) { - foreach (array('vertical', 'horizontal') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['inside']; - } - } - unset($pStyles['borders']['inside']); // not needed any more - } - - // width and height characteristics of selection, 1, 2, or 3 (for 3 or more) - $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); - $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); - - // loop through up to 3 x 3 = 9 regions - for ($x = 1; $x <= $xMax; ++$x) { - // start column index for region - $colStart = ($x == 3) ? - PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) - : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); - - // end column index for region - $colEnd = ($x == 1) ? - PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) - : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); - - for ($y = 1; $y <= $yMax; ++$y) { - - // which edges are touching the region - $edges = array(); - - // are we at left edge - if ($x == 1) { - $edges[] = 'left'; - } - - // are we at right edge - if ($x == $xMax) { - $edges[] = 'right'; - } - - // are we at top edge? - if ($y == 1) { - $edges[] = 'top'; - } - - // are we at bottom edge? - if ($y == $yMax) { - $edges[] = 'bottom'; - } - - // start row index for region - $rowStart = ($y == 3) ? - $rangeEnd[1] : $rangeStart[1] + $y - 1; - - // end row index for region - $rowEnd = ($y == 1) ? - $rangeStart[1] : $rangeEnd[1] - $yMax + $y; - - // build range for region - $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; - - // retrieve relevant style array for region - $regionStyles = $pStyles; - unset($regionStyles['borders']['inside']); - - // what are the inner edges of the region when looking at the selection - $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); - - // inner edges that are not touching the region should take the 'inside' border properties if they have been set - foreach ($innerEdges as $innerEdge) { - switch ($innerEdge) { - case 'top': - case 'bottom': - // should pick up 'horizontal' border property if set - if (isset($pStyles['borders']['horizontal'])) { - $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; - } else { - unset($regionStyles['borders'][$innerEdge]); - } - break; - case 'left': - case 'right': - // should pick up 'vertical' border property if set - if (isset($pStyles['borders']['vertical'])) { - $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; - } else { - unset($regionStyles['borders'][$innerEdge]); - } - break; - } - } - - // apply region style to region by calling applyFromArray() in simple mode - $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); - } - } - return; - } - - // Simple mode - - // First loop through cells to find out which styles are affected by this operation - $oldXfIndexes = array(); - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; - } - } - - // clone each of the affected styles, apply the style arrray, and add the new styles to the workbook - $workbook = $this->getActiveSheet()->getParent(); - foreach ($oldXfIndexes as $oldXfIndex => $dummy) { - $style = $workbook->getCellXfByIndex($oldXfIndex); - $newStyle = clone $style; - $newStyle->applyFromArray($pStyles); - - if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) { - // there is already such cell Xf in our collection - $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); - } else { - // we don't have such a cell Xf, need to add - $workbook->addCellXf($newStyle); - $newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); - } - } - - // Loop through cells again and update the XF index - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); - $oldXfIndex = $cell->getXfIndex(); - $cell->setXfIndex($newXfIndexes[$oldXfIndex]); - } - } + // Uppercase coordinate + $pRange = strtoupper($pRange); + // Is it a cell range or a single cell? + $rangeA = ''; + $rangeB = ''; + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; } else { - throw new Exception("Invalid style array passed."); + list($rangeA, $rangeB) = explode(':', $pRange); } - + + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } + + // ADVANCED MODE: + + if ($pAdvanced && isset($pStyles['borders'])) { + + // 'allborders' is a shorthand property for 'outline' and 'inside' and + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['allborders'])) { + foreach (array('outline', 'inside') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['allborders']; + } + } + unset($pStyles['borders']['allborders']); // not needed any more + } + + // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['outline'])) { + foreach (array('top', 'right', 'bottom', 'left') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['outline']; + } + } + unset($pStyles['borders']['outline']); // not needed any more + } + + // 'inside' is a shorthand property for 'vertical' and 'horizontal' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['inside'])) { + foreach (array('vertical', 'horizontal') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['inside']; + } + } + unset($pStyles['borders']['inside']); // not needed any more + } + + // width and height characteristics of selection, 1, 2, or 3 (for 3 or more) + $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); + $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); + + // loop through up to 3 x 3 = 9 regions + for ($x = 1; $x <= $xMax; ++$x) { + // start column index for region + $colStart = ($x == 3) ? + PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); + + // end column index for region + $colEnd = ($x == 1) ? + PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); + + for ($y = 1; $y <= $yMax; ++$y) { + + // which edges are touching the region + $edges = array(); + + // are we at left edge + if ($x == 1) { + $edges[] = 'left'; + } + + // are we at right edge + if ($x == $xMax) { + $edges[] = 'right'; + } + + // are we at top edge? + if ($y == 1) { + $edges[] = 'top'; + } + + // are we at bottom edge? + if ($y == $yMax) { + $edges[] = 'bottom'; + } + + // start row index for region + $rowStart = ($y == 3) ? + $rangeEnd[1] : $rangeStart[1] + $y - 1; + + // end row index for region + $rowEnd = ($y == 1) ? + $rangeStart[1] : $rangeEnd[1] - $yMax + $y; + + // build range for region + $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; + + // retrieve relevant style array for region + $regionStyles = $pStyles; + unset($regionStyles['borders']['inside']); + + // what are the inner edges of the region when looking at the selection + $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); + + // inner edges that are not touching the region should take the 'inside' border properties if they have been set + foreach ($innerEdges as $innerEdge) { + switch ($innerEdge) { + case 'top': + case 'bottom': + // should pick up 'horizontal' border property if set + if (isset($pStyles['borders']['horizontal'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + case 'left': + case 'right': + // should pick up 'vertical' border property if set + if (isset($pStyles['borders']['vertical'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + } + } + + // apply region style to region by calling applyFromArray() in simple mode + $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); + } + } + return; + } + + // SIMPLE MODE: + + // Selection type, inspect + if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) { + $selectionType = 'COLUMN'; + } else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) { + $selectionType = 'ROW'; + } else { + $selectionType = 'CELL'; + } + + // First loop through columns, rows, or cells to find out which styles are affected by this operation + switch ($selectionType) { + case 'COLUMN': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; + } + break; + + case 'ROW': + $oldXfIndexes = array(); + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) { + $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style + } else { + $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; + } + } + break; + + case 'CELL': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; + } + } + break; + } + + // clone each of the affected styles, apply the style arrray, and add the new styles to the workbook + $workbook = $this->getActiveSheet()->getParent(); + foreach ($oldXfIndexes as $oldXfIndex => $dummy) { + $style = $workbook->getCellXfByIndex($oldXfIndex); + $newStyle = clone $style; + $newStyle->applyFromArray($pStyles); + + if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) { + // there is already such cell Xf in our collection + $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); + } else { + // we don't have such a cell Xf, need to add + $workbook->addCellXf($newStyle); + $newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); + } + } + + // Loop through columns, rows, or cells again and update the XF index + switch ($selectionType) { + case 'COLUMN': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col); + $oldXfIndex = $columnDimension->getXfIndex(); + $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; + + case 'ROW': + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $rowDimension = $this->getActiveSheet()->getRowDimension($row); + $oldXfIndex = $rowDimension->getXfIndex() === null ? + 0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style + $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; + + case 'CELL': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); + $oldXfIndex = $cell->getXfIndex(); + $cell->setXfIndex($newXfIndexes[$oldXfIndex]); + } + } + break; + } + } else { + // not a supervisor, just apply the style array directly on style object if (array_key_exists('fill', $pStyles)) { $this->getFill()->applyFromArray($pStyles['fill']); } @@ -585,7 +634,7 @@ class PHPExcel_Style implements PHPExcel_IComparable * @return PHPExcel_Style_Conditional[] */ public function getConditionalStyles() { - return $this->getActiveSheet()->getConditionalStyles($this->getXActiveCell()); + return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell()); } /** @@ -596,7 +645,7 @@ class PHPExcel_Style implements PHPExcel_IComparable */ public function setConditionalStyles($pValue = null) { if (is_array($pValue)) { - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($this->getXSelectedCells()) as $cellReference) { + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($this->getSelectedCells()) as $cellReference) { $this->getActiveSheet()->setConditionalStyles($cellReference, $pValue); } } @@ -635,37 +684,6 @@ class PHPExcel_Style implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Get own index in style collection * diff --git a/libraries/PHPExcel/PHPExcel/Style/Alignment.php b/libraries/PHPExcel/PHPExcel/Style/Alignment.php index 6958b6a8a..fa52e0869 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Alignment.php +++ b/libraries/PHPExcel/PHPExcel/Style/Alignment.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Alignment implements PHPExcel_IComparable { @@ -190,9 +190,9 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -201,9 +201,9 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -238,7 +238,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('horizontal', $pStyles)) { $this->setHorizontal($pStyles['horizontal']); @@ -290,7 +290,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('horizontal' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_horizontal = $pValue; @@ -323,7 +323,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('vertical' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_vertical = $pValue; } @@ -359,7 +359,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable if ( ($pValue >= -90 && $pValue <= 90) || $pValue == -165 ) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('rotation' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_textRotation = $pValue; } @@ -394,7 +394,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('wrap' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_wrapText = $pValue; } @@ -425,7 +425,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('shrinkToFit' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_shrinkToFit = $pValue; } @@ -458,7 +458,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('indent' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_indent = $pValue; } @@ -485,37 +485,6 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Border.php b/libraries/PHPExcel/PHPExcel/Style/Border.php index 2509d71c6..edaeaf301 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Border.php +++ b/libraries/PHPExcel/PHPExcel/Style/Border.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Border implements PHPExcel_IComparable { @@ -200,9 +200,9 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -211,9 +211,9 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -289,7 +289,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('style', $pStyles)) { $this->setBorderStyle($pStyles['style']); @@ -329,7 +329,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('style' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_borderStyle = $pValue; } @@ -358,7 +358,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_color = $color; } @@ -381,37 +381,6 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Borders.php b/libraries/PHPExcel/PHPExcel/Style/Borders.php index 7b6ae30b9..4a6b3460b 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Borders.php +++ b/libraries/PHPExcel/PHPExcel/Style/Borders.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Borders implements PHPExcel_IComparable { @@ -54,6 +54,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable const DIAGONAL_NONE = 0; const DIAGONAL_UP = 1; const DIAGONAL_DOWN = 2; + const DIAGONAL_BOTH = 3; /** * Left @@ -241,9 +242,9 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -252,9 +253,9 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -309,7 +310,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('left', $pStyles)) { $this->getLeft()->applyFromArray($pStyles['left']); @@ -470,7 +471,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('diagonaldirection' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_diagonalDirection = $pValue; } @@ -497,37 +498,6 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Color.php b/libraries/PHPExcel/PHPExcel/Style/Color.php index 22840cd65..e17595c0d 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Color.php +++ b/libraries/PHPExcel/PHPExcel/Style/Color.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Color implements PHPExcel_IComparable { @@ -171,9 +171,9 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -182,9 +182,9 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -226,7 +226,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('rgb', $pStyles)) { $this->setRGB($pStyles['rgb']); @@ -265,7 +265,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('argb' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_argb = $pValue; } @@ -296,7 +296,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('argb' => 'FF' . $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_argb = 'FF' . $pValue; } @@ -404,37 +404,6 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Conditional.php b/libraries/PHPExcel/PHPExcel/Style/Conditional.php index e389ec222..e0520c8ec 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Conditional.php +++ b/libraries/PHPExcel/PHPExcel/Style/Conditional.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Conditional implements PHPExcel_IComparable { @@ -276,37 +276,6 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Fill.php b/libraries/PHPExcel/PHPExcel/Style/Fill.php index 6875b31dc..2d5fbe102 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Fill.php +++ b/libraries/PHPExcel/PHPExcel/Style/Fill.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Fill implements PHPExcel_IComparable { @@ -192,9 +192,9 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -203,9 +203,9 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -244,7 +244,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('type', $pStyles)) { $this->setFillType($pStyles['type']); @@ -289,7 +289,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function setFillType($pValue = PHPExcel_Style_Fill::FILL_NONE) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('type' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_fillType = $pValue; } @@ -317,7 +317,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable public function setRotation($pValue = 0) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('rotation' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_rotation = $pValue; } @@ -346,7 +346,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStartColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_startColor = $color; } @@ -375,7 +375,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getEndColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_endColor = $color; } @@ -400,37 +400,6 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/Font.php b/libraries/PHPExcel/PHPExcel/Style/Font.php index 1caa8be3b..2adaff11c 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Font.php +++ b/libraries/PHPExcel/PHPExcel/Style/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Font implements PHPExcel_IComparable { @@ -207,9 +207,9 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -218,9 +218,9 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -259,7 +259,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('name', $pStyles)) { $this->setName($pStyles['name']); @@ -319,7 +319,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('name' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_name = $pValue; } @@ -350,7 +350,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('size' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_size = $pValue; } @@ -381,7 +381,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('bold' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_bold = $pValue; } @@ -412,7 +412,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('italic' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_italic = $pValue; } @@ -443,7 +443,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('superScript' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_superScript = $pValue; $this->_subScript = !$pValue; @@ -475,7 +475,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('subScript' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_subScript = $pValue; $this->_superScript = !$pValue; @@ -507,7 +507,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('underline' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_underline = $pValue; } @@ -559,7 +559,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('strike' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_strikethrough = $pValue; } @@ -588,7 +588,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_color = $color; } @@ -618,37 +618,6 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php b/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php index a9df568ec..83a8fc967 100644 --- a/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php +++ b/libraries/PHPExcel/PHPExcel/Style/NumberFormat.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,7 +49,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Calculation/Functions.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable { @@ -203,9 +203,9 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -214,9 +214,9 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -248,7 +248,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('code', $pStyles)) { $this->setFormatCode($pStyles['code']); @@ -288,7 +288,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('code' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_formatCode = $pValue; $this->_builtInFormatCode = self::builtInFormatCodeIndex($pValue); @@ -318,7 +318,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('code' => self::builtInFormatCode($pValue))); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_builtInFormatCode = $pValue; $this->_formatCode = self::builtInFormatCode($pValue); @@ -446,37 +446,6 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ @@ -491,15 +460,59 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable } } + private static $_dateFormatReplacements = array( + // first remove escapes related to non-format characters + '\\' => '', + // 12-hour suffix + 'am/pm' => 'A', + // 4-digit year + 'yyyy' => 'Y', + // 2-digit year + 'yy' => 'y', + // first letter of month - no php equivalent + 'mmmmm' => 'M', + // full month name + 'mmmm' => 'F', + // short month name + 'mmm' => 'M', + // mm is minutes if time or month w/leading zero + ':mm' => ':i', + // month leading zero + 'mm' => 'm', + // month no leading zero + 'm' => 'n', + // full day of week name + 'dddd' => 'l', + // short day of week name + 'ddd' => 'D', + // days leading zero + 'dd' => 'd', + // days no leading zero + 'd' => 'j', + // seconds + 'ss' => 's', + // fractional seconds - no php equivalent + '.s' => '' + ); + private static $_dateFormatReplacements24 = array( + 'hh' => 'H', + 'h' => 'G' + ); + private static $_dateFormatReplacements12 = array( + 'hh' => 'h', + 'h' => 'g' + ); + /** * Convert a value in a pre-defined format to a PHP string * * @param mixed $value Value to format * @param string $format Format code + * @param array $callBack Callback function for additional formatting of string * @return string Formatted string */ - public static function toFormattedString($value = '', $format = '') { - // For now we do not treat strings although part 4 of a format code affects strings + public static function toFormattedString($value = '', $format = '', $callBack = null) { + // For now we do not treat strings although section 4 of a format code affects strings if (!is_numeric($value)) return $value; // For 'General' format code, we just pass the value although this is not entirely the way Excel does it, @@ -508,82 +521,94 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable return $value; } - // Get the parts, there can be up to four parts - $parts = explode(';', $format); + // Get the sections, there can be up to four sections + $sections = explode(';', $format); - // We should really fetch the relevant part depending on whether we have a positive number, - // negative number, zero, or text. But for now we just use first part - $format = $parts[0]; + // Fetch the relevant section depending on whether number is positive, negative, or zero? + // Text not supported yet. + // Here is how the sections apply to various values in Excel: + // 1 section: [POSITIVE/NEGATIVE/ZERO/TEXT] + // 2 sections: [POSITIVE/ZERO/TEXT] [NEGATIVE] + // 3 sections: [POSITIVE/TEXT] [NEGATIVE] [ZERO] + // 4 sections: [POSITIVE] [NEGATIVE] [ZERO] [TEXT] + switch (count($sections)) { + case 1: + $format = $sections[0]; + break; - if (preg_match("/^[hmsdy]/i", $format)) { // custom datetime format + case 2: + $format = ($value >= 0) ? $sections[0] : $sections[1]; + $value = abs($value); // Use the absolute value + break; + + case 3: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + case 4: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + default: + // something is wrong, just use first section + $format = $sections[0]; + break; + } + + // Save format with color information for later use below + $formatColor = $format; + + // Strip color information + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + $format = preg_replace($color_regex, '', $format); + + // Let's begin inspecting the format and converting the value to a formatted string + if (preg_match('/^(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $format)) { // datetime format // dvc: convert Excel formats to PHP date formats - // first remove escapes related to non-format characters + + // strip off first part containing e.g. [$-F800] or [$USD-409] + // general syntax: [$-] + // language info is in hexadecimal + $format = preg_replace('/^(\[\$[A-Z]*-[0-9A-F]*\])/i', '', $format); // OpenOffice.org uses upper-case number formats, e.g. 'YYYY', convert to lower-case $format = strtolower($format); - $format = str_replace('\\', '', $format); - - // 4-digit year - $format = str_replace('yyyy', 'Y', $format); - // 2-digit year - $format = str_replace('yy', 'y', $format); - // first letter of month - no php equivalent - $format = str_replace('mmmmm', 'M', $format); - // full month name - $format = str_replace('mmmm', 'F', $format); - // short month name - $format = str_replace('mmm', 'M', $format); - // mm is minutes if time or month w/leading zero - $format = str_replace(':mm', ':i', $format); - // tmp place holder - $format = str_replace('mm', 'x', $format); - // month no leading zero - $format = str_replace('m', 'n', $format); - // month leading zero - $format = str_replace('x', 'm', $format); - // 12-hour suffix - $format = str_replace('am/pm', 'A', $format); - // full day of week name - $format = str_replace('dddd', 'l', $format); - // short day of week name - $format = str_replace('ddd', 'D', $format); - // tmp place holder - $format = str_replace('dd', 'x', $format); - // days no leading zero - $format = str_replace('d', 'j', $format); - // days leading zero - $format = str_replace('x', 'd', $format); - // seconds - $format = str_replace('ss', 's', $format); - // fractional seconds - no php equivalent - $format = str_replace('.s', '', $format); - - if (!strpos($format,'A')) { // 24-hour format - $format = str_replace('h', 'H', $format); + $format = strtr($format,self::$_dateFormatReplacements); + if (!strpos($format,'A')) { // 24-hour time format + $format = strtr($format,self::$_dateFormatReplacements24); + } else { // 12-hour time format + $format = strtr($format,self::$_dateFormatReplacements12); } - return gmdate($format, PHPExcel_Shared_Date::ExcelToPHP($value)); + $value = gmdate($format, PHPExcel_Shared_Date::ExcelToPHP($value)); } else if (preg_match('/%$/', $format)) { // % number format if ($format === self::FORMAT_PERCENTAGE) { - return round( (100 * $value), 0) . '%'; - } - if (preg_match('/\.[#0]+/i', $format, $m)) { - $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); - $format = str_replace($m[0], $s, $format); - } - if (preg_match('/^[#0]+/', $format, $m)) { - $format = str_replace($m[0], strlen($m[0]), $format); - } - $format = '%' . str_replace('%', 'f%%', $format); + $value = round( (100 * $value), 0) . '%'; + } else { + if (preg_match('/\.[#0]+/i', $format, $m)) { + $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); + $format = str_replace($m[0], $s, $format); + } + if (preg_match('/^[#0]+/', $format, $m)) { + $format = str_replace($m[0], strlen($m[0]), $format); + } + $format = '%' . str_replace('%', 'f%%', $format); - return sprintf($format, 100 * $value); + $value = sprintf($format, 100 * $value); + } } else { if (preg_match ("/^([0-9.,-]+)$/", $value)) { if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { - return 'EUR ' . sprintf('%1.2f', $value); + $value = 'EUR ' . sprintf('%1.2f', $value); } else { // In Excel formats, "_" is used to add spacing, which we can't do in HTML @@ -618,7 +643,8 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $adjustedDecimalPart = $decimalPart/$GCD; $adjustedDecimalDivisor = $decimalDivisor/$GCD; - if (strpos($format,'0') !== false) { + if ((strpos($format,'0') !== false) || (substr($format,0,3) == '? ?')) { + if ($integerPart == 0) { $integerPart = ''; } $value = "$sign$integerPart $adjustedDecimalPart/$adjustedDecimalDivisor"; } else { $adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor; @@ -633,12 +659,13 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $dec = $matches[2]; $right = $matches[3]; if ($useThousands) { - $localeconv = localeconv(); - if (($localeconv['thousands_sep'] == '') || ($localeconv['decimal_point'] == '')) { - $value = number_format($value, strlen($right), $localeconv['mon_decimal_point'], $localeconv['mon_thousands_sep']); - } else { - $value = number_format($value, strlen($right), $localeconv['decimal_point'], $localeconv['thousands_sep']); - } + $value = number_format( + $value + , strlen($right) + , PHPExcel_Shared_String::getDecimalSeparator() + , PHPExcel_Shared_String::getThousandsSeparator() + ); + } else { $sprintf_pattern = "%1." . strlen($right) . "f"; $value = sprintf($sprintf_pattern, $value); @@ -646,13 +673,16 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $value = preg_replace($number_regex, $value, $format); } } - - return $value; - } } - - return $value; } + + // Additional formatting provided by callback function + if ($callBack !== null) { + list($writerInstance, $function) = $callBack; + $value = $writerInstance->$function($value, $formatColor); + } + + return $value; } } diff --git a/libraries/PHPExcel/PHPExcel/Style/Protection.php b/libraries/PHPExcel/PHPExcel/Style/Protection.php index 57e974d33..12611d13b 100644 --- a/libraries/PHPExcel/PHPExcel/Style/Protection.php +++ b/libraries/PHPExcel/PHPExcel/Style/Protection.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,7 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version 1.4.5, 2007-08-23 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php'; * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Protection implements PHPExcel_IComparable { @@ -149,9 +149,9 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->getActiveSheet()->getXSelectedCells(); + return $this->getActiveSheet()->getSelectedCells(); } /** @@ -160,9 +160,9 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable * * @return string E.g. 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->getActiveSheet()->getXActiveCell(); + return $this->getActiveSheet()->getActiveCell(); } /** @@ -190,7 +190,7 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable public function applyFromArray($pStyles = null) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { if (array_key_exists('locked', $pStyles)) { $this->setLocked($pStyles['locked']); @@ -226,7 +226,7 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable public function setLocked($pValue = self::PROTECTION_INHERIT) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('locked' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_locked = $pValue; } @@ -254,7 +254,7 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable public function setHidden($pValue = self::PROTECTION_INHERIT) { if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('hidden' => $pValue)); - $this->getActiveSheet()->getStyle($this->getXSelectedCells())->applyFromArray($styleArray); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); } else { $this->_hidden = $pValue; } @@ -277,37 +277,6 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet.php b/libraries/PHPExcel/PHPExcel/Worksheet.php index c54ab702f..74bd65266 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -88,6 +88,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style.php'; /** PHPExcel_Style_Fill */ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Fill.php'; +/** PHPExcel_Style_Color */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; + /** PHPExcel_Style_NumberFormat */ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php'; @@ -112,7 +115,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/ReferenceHelper.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet implements PHPExcel_IComparable { @@ -120,6 +123,11 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable const BREAK_NONE = 0; const BREAK_ROW = 1; const BREAK_COLUMN = 2; + + /* Sheet state */ + const SHEETSTATE_VISIBLE = 'visible'; + const SHEETSTATE_HIDDEN = 'hidden'; + const SHEETSTATE_VERYHIDDEN = 'veryHidden'; /** * Parent spreadsheet @@ -176,6 +184,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @var string */ private $_title; + + /** + * Sheet state + * + * @var string + */ + private $_sheetState; /** * Page setup @@ -304,43 +319,36 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable private $_comments = array(); /** - * Selected cell + * Active cell. (Only one!) * * @var string */ - private $_selectedCell = 'A1'; + private $_activeCell = 'A1'; /** - * Temporary property used by style supervisor. Will be removed + * Selected cells * * @var string */ - private $_xActiveCell = 'A1'; - - /** - * Temporary property used by style supervisor. Will be removed - * - * @var string - */ - private $_xSelectedCells = 'A1:A1'; + private $_selectedCells = 'A1'; /** * Cached highest column * * @var string */ - private $_cachedHighestColumn = null; + private $_cachedHighestColumn = 'A'; /** * Cached highest row * * @var int */ - private $_cachedHighestRow = null; + private $_cachedHighestRow = 1; /** * Right-to-left? - * + * * @var boolean */ private $_rightToLeft = false; @@ -359,6 +367,13 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ private $_dataValidationCollection = array(); + /** + * Tab color + * + * @var PHPExcel_Style_Color + */ + private $_tabColor; + /** * Create a new worksheet * @@ -370,6 +385,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Set parent and title $this->_parent = $pParent; $this->setTitle($pTitle); + $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); // Set page setup $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); @@ -404,6 +420,28 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(null); } + /** + * Check sheet title for valid Excel syntax + * + * @param string $pValue The string to check + * @return string The valid string + * @throws Exception + */ + private static function _checkSheetTitle($pValue) + { + // Some of the printable ASCII characters are invalid: * : / \ ? [ ] + if (preg_match('/(\\*|\\:|\\/|\\\\|\\?|\\[|\\])/', $pValue)) { + throw new Exception('Invalid character found in sheet title'); + } + + // Maximum 31 characters allowed for sheet title + if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { + throw new Exception('Maximum 31 characters allowed in sheet title.'); + } + + return $pValue; + } + /** * Get collection of cells * @@ -555,45 +593,56 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); } - /** - * Calculate widths for auto-size columns - * - * @param boolean $calculateMergeCells Calculate merge cell width - * @return PHPExcel_Worksheet; - */ - public function calculateColumnWidths($calculateMergeCells = false) - { + /** + * Calculate widths for auto-size columns + * + * @param boolean $calculateMergeCells Calculate merge cell width + * @return PHPExcel_Worksheet; + */ + public function calculateColumnWidths($calculateMergeCells = false) + { + // initialize $autoSizes array $autoSizes = array(); - foreach ($this->getColumnDimensions() as $colDimension) { + foreach ($this->getColumnDimensions() as $colDimension) { if ($colDimension->getAutoSize()) { $autoSizes[$colDimension->getColumnIndex()] = -1; } - } - - foreach ($this->getCellCollection() as $cell) { - if (isset($autoSizes[$cell->getColumn()])) { - $cellValue = $cell->getCalculatedValue(); - - foreach ($this->getMergeCells() as $cells) { - if ($cell->isInRange($cells) && !$calculateMergeCells) { - $cellValue = ''; // do not calculate merge cells - } - } - - $autoSizes[$cell->getColumn()] = max( - (float)$autoSizes[$cell->getColumn()], - (float)PHPExcel_Shared_Font::calculateColumnWidth( - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSize(), - false, - $cellValue, - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation() - ) - ); - } } - foreach ($autoSizes as $columnIndex => $width) { - if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); - $this->getColumnDimension($columnIndex)->setWidth($width); + + // There is only something to do if there are some auto-size columns + if (count($autoSizes) > 0) { + // loop though all cells in sheet expand $autoSizes + foreach ($this->getCellCollection(false) as $cell) { + if (isset($autoSizes[$cell->getColumn()])) { + // Calculated value + $cellValue = $cell->getCalculatedValue(); + + // To formatted string + $cellValue = PHPExcel_Style_NumberFormat::toFormattedString($cellValue, $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode()); + + foreach ($this->getMergeCells() as $cells) { + if ($cell->isInRange($cells) && !$calculateMergeCells) { + $cellValue = ''; // do not calculate merge cells + } + } + + $autoSizes[$cell->getColumn()] = max( + (float)$autoSizes[$cell->getColumn()], + (float)PHPExcel_Shared_Font::calculateColumnWidth( + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $cellValue, + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->getDefaultStyle()->getFont() + ) + ); + } + } + + // adjust column widths + foreach ($autoSizes as $columnIndex => $width) { + if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); + $this->getColumnDimension($columnIndex)->setWidth($width); + } } return $this; @@ -642,7 +691,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * Set title * * @param string $pValue String containing the dimension of this worksheet - * @throws Exception * @return PHPExcel_Worksheet */ public function setTitle($pValue = 'Worksheet') @@ -652,10 +700,8 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return; } - // Maximum 31 characters allowed for sheet title - if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { - throw new Exception('Maximum 31 characters allowed in sheet title.'); - } + // Syntax check + self::_checkSheetTitle($pValue); // Old title $oldTitle = $this->getTitle(); @@ -684,7 +730,27 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this; } - + + /** + * Get sheet state + * + * @return string Sheet state (visible, hidden, veryHidden) + */ + public function getSheetState() { + return $this->_sheetState; + } + + /** + * Set sheet state + * + * @param string $value Sheet state (visible, hidden, veryHidden) + * @return PHPExcel_Worksheet + */ + public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { + $this->_sheetState = $value; + return $this; + } + /** * Get page setup * @@ -802,36 +868,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function getHighestColumn() { - // Cached? - if (!is_null($this->_cachedHighestColumn)) { - return $this->_cachedHighestColumn; - } - - // Highest column - $highestColumn = -1; - - // Loop trough cells - foreach ($this->_cellCollection as $cell) { - if ($highestColumn < PHPExcel_Cell::columnIndexFromString($cell->getColumn())) { - $highestColumn = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); - } - } - - // Loop trough column dimensions - foreach ($this->_columnDimensions as $dimension) { - if ($highestColumn < PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())) { - $highestColumn = PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex()); - } - } - - // Return & cache - if ($highestColumn < 0) { - $this->_cachedHighestColumn = 'A'; - } else { - $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); - } - - return $this->_cachedHighestColumn; + return $this->_cachedHighestColumn; } /** @@ -841,33 +878,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function getHighestRow() { - // Cached? - if (!is_null($this->_cachedHighestRow)) { - return $this->_cachedHighestRow; - } - - // Highest row - $highestRow = 1; - - // Loop trough cells - foreach ($this->_cellCollection as $cell) { - if ($cell->getRow() > $highestRow) { - $highestRow = $cell->getRow(); - } - } - - // Loop trough row dimensions - foreach ($this->_rowDimensions as $dimension) { - if ($highestRow < $dimension->getRowIndex()) { - $highestRow = $dimension->getRowIndex(); - } - } - - // Cache - $this->_cachedHighestRow = $highestRow; - - // Return - return $highestRow; + return $this->_cachedHighestRow; } /** @@ -949,7 +960,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Named range? if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && - (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches))) { + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); if (!is_null($namedRange)) { $pCoordinate = $namedRange->getRange(); @@ -959,6 +970,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } else { throw new Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); } + } else { + //Allow named ranges within the same sheet. + return $this->getCell($pCoordinate); } } } @@ -971,14 +985,36 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } elseif (strpos($pCoordinate,'$') !== false) { throw new Exception('Cell coordinate must not be absolute.'); } else { + // Create new cell object + // Coordinates $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); $this->_cellCollection[$pCoordinate] = new PHPExcel_Cell($aCoordinates[0], $aCoordinates[1], null, PHPExcel_Cell_DataType::TYPE_NULL, $this); $this->_cellCollectionIsSorted = false; - $this->_cachedHighestColumn = null; - $this->_cachedHighestRow = null; + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) + $this->_cachedHighestColumn = $aCoordinates[0]; + + if ($this->_cachedHighestRow < $aCoordinates[1]) + $this->_cachedHighestRow = $aCoordinates[1]; + + // Cell needs appropriate xfIndex + $rowDimensions = $this->getRowDimensions(); + $columnDimensions = $this->getColumnDimensions(); + + if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) { + // then there is a row dimension with explicit style, assign it to the cell + $this->_cellCollection[$pCoordinate]->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); + + } else if ( isset($columnDimensions[$aCoordinates[0]]) ) { + // then there is a column dimension, assign it to the cell + $this->_cellCollection[$pCoordinate]->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); + + } else { + // set to default index + $this->_cellCollection[$pCoordinate]->setXfIndex(0); + } return $this->_cellCollection[$pCoordinate]; } @@ -1001,8 +1037,11 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_cellCollection[$coordinate] = new PHPExcel_Cell($columnLetter, $pRow, null, PHPExcel_Cell_DataType::TYPE_NULL, $this); $this->_cellCollectionIsSorted = false; - $this->_cachedHighestColumn = null; - $this->_cachedHighestRow = null; + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) + $this->_cachedHighestColumn = $pColumn; + + if ($this->_cachedHighestRow < $pRow) + $this->_cachedHighestRow = $pRow; } return $this->_cellCollection[$coordinate]; @@ -1025,7 +1064,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Named range? if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && - (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches))) { + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); if (!is_null($namedRange)) { $pCoordinate = $namedRange->getRange(); @@ -1081,7 +1120,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Get row dimension if (!isset($this->_rowDimensions[$pRow])) { $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); - $this->_cachedHighestRow = null; + + if ($this->_cachedHighestRow < $pRow) + $this->_cachedHighestRow = $pRow; } return $this->_rowDimensions[$pRow]; } @@ -1100,7 +1141,9 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Fetch dimensions if (!isset($this->_columnDimensions[$pColumn])) { $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); - $this->_cachedHighestColumn = null; + + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) + $this->_cachedHighestColumn = $pColumn; } return $this->_columnDimensions[$pColumn]; } @@ -1147,9 +1190,14 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable * @throws Exception * @return PHPExcel_Worksheet */ - public function setDefaultStyle(PHPExcel_Style $value) + public function setDefaultStyle(PHPExcel_Style $pValue) { - $this->_parent->setDefaultStyle($value); + $this->_parent->getDefaultStyle()->applyFromArray(array( + 'font' => array( + 'name' => $pValue->getFont()->getName(), + 'size' => $pValue->getFont()->getSize(), + ), + )); return $this; } @@ -1166,7 +1214,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $this->_parent->setActiveSheetIndex($this->_parent->getIndex($this)); // set cell coordinate as active - $this->setXSelectedCells($pCellCoordinate); + $this->setSelectedCells($pCellCoordinate); return $this->_parent->getCellXfSupervisor(); } @@ -1317,7 +1365,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $rangeEnd = $tmp; } - // Loop trough cells and apply styles + // Loop through cells and apply styles for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { $this->getCell(PHPExcel_Cell::stringFromColumnIndex($col) . $row)->setXfIndex($xfIndex); @@ -1472,7 +1520,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } /** - * Get merge cells + * Get merge cells array. * * @return array[] */ @@ -1481,6 +1529,19 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this->_mergeCells; } + /** + * Set merge cells array for the entire sheet. Use instead mergeCells() to merge + * a single cell range. + * + * @param array + */ + public function setMergeCells($pValue = array()) + { + $this->_mergeCells = $pValue; + + return $this; + } + /** * Set protection on a cell range * @@ -1912,72 +1973,76 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable /** * Get selected cell * + * @deprecated * @return string */ public function getSelectedCell() { - return $this->_selectedCell; + return $this->getSelectedCells(); } /** - * Temporary method used by style supervisor. Will be removed + * Get active cell * - * @return string + * @return string Example: 'A1' */ - public function getXActiveCell() + public function getActiveCell() { - return $this->_xActiveCell; + return $this->_activeCell; } /** - * Temporary method used by style supervisor. Will be removed + * Get selected cells * * @return string */ - public function getXSelectedCells() + public function getSelectedCells() { - return $this->_xSelectedCells; + return $this->_selectedCells; } /** * Selected cell * * @param string $pCell Cell (i.e. A1) - * @throws Exception * @return PHPExcel_Worksheet */ - public function setSelectedCell($pCell = '') + public function setSelectedCell($pCoordinate = 'A1') { - // Uppercase coordinate - $pCell = strtoupper($pCell); - - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - $this->_selectedCell = $pCell; - } else { - throw new Exception('Selected cell can not be set on a range of cells.'); - } - return $this; + return $this->setSelectedCells($pCoordinate); } /** - * Temporary method used by style supervisor. Will be removed + * Select a range of cells. * - * @param string $pCell Cell (i.e. A1) + * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' * @throws Exception * @return PHPExcel_Worksheet */ - public function setXSelectedCells($pCoordinate = 'A1:A1') + public function setSelectedCells($pCoordinate = 'A1') { - // Uppercase coordinate + // Uppercase coordinate $pCoordinate = strtoupper($pCoordinate); + // Convert 'A' to 'A:A' + $pCoordinate = preg_replace('/^([A-Z]+)$/', '${1}:${1}', $pCoordinate); + + // Convert '1' to '1:1' + $pCoordinate = preg_replace('/^([0-9]+)$/', '${1}:${1}', $pCoordinate); + + // Convert 'A:C' to 'A1:C1048576' + $pCoordinate = preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $pCoordinate); + + // Convert '1:3' to 'A1:XFD3' + $pCoordinate = preg_replace('/^([0-9]+):([0-9]+)$/', 'A${1}:XFD${2}', $pCoordinate); + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { list($first, ) = PHPExcel_Cell::splitRange($pCoordinate); - $this->_xActiveCell = $first[0]; + $this->_activeCell = $first[0]; } else { - $this->_xActiveCell = $pCoordinate; + $this->_activeCell = $pCoordinate; } - $this->_xSelectedCells = $pCoordinate; + $this->_selectedCells = $pCoordinate; return $this; } @@ -1991,24 +2056,24 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable */ public function setSelectedCellByColumnAndRow($pColumn = 0, $pRow = 0) { - return $this->setSelectedCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + return $this->setSelectedCells(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); } /** * Get right-to-left - * + * * @return boolean */ public function getRightToLeft() { return $this->_rightToLeft; } - + /** * Set right-to-left - * + * * @param boolean $value Right-to-left true/false * @return PHPExcel_Worksheet - */ + */ public function setRightToLeft($value = false) { $this->_rightToLeft = $value; return $this; @@ -2028,7 +2093,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable list ($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($pCell); $startColumn = PHPExcel_Cell::columnIndexFromString($startColumn) - 1; - // Loop trough $source + // Loop through $source $currentRow = $startRow - 1; $rowData = null; foreach ($source as $rowData) { @@ -2071,7 +2136,7 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; - // Loop trough cells + // Loop through cells for ($row = $dimension[0][1]; $row <= $dimension[1][1]; ++$row) { for ($column = $dimension[0][0]; $column <= $dimension[1][0]; ++$column) { // Cell exists? @@ -2125,6 +2190,10 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable $iterator->next(); } + // Lookup highest column and highest row if cells are cleaned + $highestColumn = -1; + $highestRow = 1; + // Find cells that can be cleaned foreach ($this->_cellCollection as $coordinate => $cell) { // Can be cleaned? @@ -2145,10 +2214,42 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable // Clean? if ($canBeCleaned) { + // Remove the cell unset($this->_cellCollection[$coordinate]); - } + } else { + // Determine highest column and row + if ($highestColumn < PHPExcel_Cell::columnIndexFromString($cell->getColumn())) { + $highestColumn = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); + } + if ($cell->getRow() > $highestRow) { + $highestRow = $cell->getRow(); + } + } } + // Loop through column dimensions + foreach ($this->_columnDimensions as $dimension) { + if ($highestColumn < PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())) { + $highestColumn = PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex()); + } + } + + // Loop through row dimensions + foreach ($this->_rowDimensions as $dimension) { + if ($highestRow < $dimension->getRowIndex()) { + $highestRow = $dimension->getRowIndex(); + } + } + + // Cache values + if ($highestColumn < 0) { + $this->_cachedHighestColumn = 'A'; + } else { + $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); + } + $this->_cachedHighestRow = $highestRow; + + // Return return $this; } @@ -2167,37 +2268,6 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Extract worksheet title from range. * @@ -2350,6 +2420,42 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable return $this->_dataValidationCollection; } + /** + * Get tab color + * + * @return PHPExcel_Style_Color + */ + public function getTabColor() + { + if (is_null($this->_tabColor)) + $this->_tabColor = new PHPExcel_Style_Color(); + + return $this->_tabColor; + } + + /** + * Reset tab color + * + * @return PHPExcel_Worksheet + */ + public function resetTabColor() + { + $this->_tabColor = null; + unset($this->_tabColor); + + return $this; + } + + /** + * Tab color set? + * + * @return boolean + */ + public function isTabColorSet() + { + return !is_null($this->_tabColor); + } + /** * Copy worksheet (!= clone!) * diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php index 364689863..79f8c1611 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -48,7 +48,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -486,37 +486,6 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php b/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php index 6581cab62..f0683e6e4 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/CellIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -51,7 +51,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_CellIterator extends IteratorIterator { @@ -115,20 +115,7 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator * @return PHPExcel_Cell */ public function current() { - $cellExists = $this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex); - if ( ($this->_onlyExistingCells && $cellExists) || (!$this->_onlyExistingCells) ) { - return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); - } else if ($this->_onlyExistingCells && !$cellExists) { - // Loop untill we find one - while ($this->valid()) { - $this->next(); - if ($this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex)) { - return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); - } - } - } - - return null; + return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); } /** @@ -153,7 +140,23 @@ class PHPExcel_Worksheet_CellIterator extends IteratorIterator * @return boolean */ public function valid() { - return $this->_position < PHPExcel_Cell::columnIndexFromString( $this->_subject->getHighestColumn() ); + // columnIndexFromString() returns an index based at one, + // treat it as a count when comparing it to the base zero + // position. + $columnCount = PHPExcel_Cell::columnIndexFromString($this->_subject->getHighestColumn()); + + if ($this->_onlyExistingCells) { + // If we aren't looking at an existing cell, either + // because the first column doesn't exist or next() has + // been called onto a nonexistent cell, then loop until we + // find one, or pass the last column. + while ($this->_position < $columnCount && + !$this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex)) { + ++$this->_position; + } + } + + return $this->_position < $columnCount; } /** diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php b/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php index ada5bf166..7b6810fbf 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_ColumnDimension { @@ -78,9 +78,16 @@ class PHPExcel_Worksheet_ColumnDimension * @var bool */ private $_collapsed; - + + /** + * Index to cellXf + * + * @var int + */ + private $_xfIndex; + /** - * Create a new PHPExcel_Worksheet_RowDimension + * Create a new PHPExcel_Worksheet_ColumnDimension * * @param string $pIndex Character column index */ @@ -93,6 +100,9 @@ class PHPExcel_Worksheet_ColumnDimension $this->_visible = true; $this->_outlineLevel = 0; $this->_collapsed = false; + + // set default index to cellXf + $this->_xfIndex = 0; } /** @@ -222,6 +232,28 @@ class PHPExcel_Worksheet_ColumnDimension return $this; } + /** + * Get index to cellXf + * + * @return int + */ + public function getXfIndex() + { + return $this->_xfIndex; + } + + /** + * Set index to cellXf + * + * @param int $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setXfIndex($pValue = 0) + { + $this->_xfIndex = $pValue; + return $this; + } + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ @@ -235,4 +267,5 @@ class PHPExcel_Worksheet_ColumnDimension } } } + } diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php index 780662e9e..e6f84e226 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -153,37 +153,6 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php index c931671fd..a294e5a0e 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -48,7 +48,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php'; * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable { @@ -289,37 +289,6 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php index b985bf8b3..ef60e77a9 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -103,7 +103,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/HeaderFooterDrawing.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_HeaderFooter { @@ -457,7 +457,7 @@ class PHPExcel_Worksheet_HeaderFooter /** * Get header/footer images * - * @return HPExcel_Worksheet_HeaderFooterDrawing[] + * @return PHPExcel_Worksheet_HeaderFooterDrawing[] */ public function getImages() { // Sort array diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php index 3589cde4e..d3be4b75a 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing implements PHPExcel_IComparable { @@ -354,37 +354,6 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php b/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php index 5d80d7a57..05a45dfee 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Drawing/Shadow.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -205,37 +205,6 @@ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing im ); } - /** - * Hash index - * - * @var string - */ - private $_hashIndex; - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() { - return $this->_hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) { - $this->_hashIndex = $value; - } - /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php b/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php index aad7d2091..80ee4cfe0 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/PageMargins.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_PageMargins { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php b/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php index d7584a32e..1424fe062 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/PageSetup.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -102,7 +102,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_PageSetup { @@ -203,6 +203,14 @@ class PHPExcel_Worksheet_PageSetup */ private $_scale; + /** + * Fit To Page + * Whether scale or fitToWith / fitToHeight applies + * + * @var boolean + */ + private $_fitToPage; + /** * Fit To Height * Number of vertical pages to fit on @@ -253,6 +261,13 @@ class PHPExcel_Worksheet_PageSetup * @var string */ private $_printArea = null; + + /** + * First page number + * + * @var int + */ + private $_firstPageNumber = null; /** * Create a new PHPExcel_Worksheet_PageSetup @@ -262,14 +277,16 @@ class PHPExcel_Worksheet_PageSetup // Initialise values $this->_paperSize = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER; $this->_orientation = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT; - $this->_scale = null; - $this->_fitToHeight = null; - $this->_fitToWidth = null; + $this->_scale = 100; + $this->_fitToPage = false; + $this->_fitToHeight = 1; + $this->_fitToWidth = 1; $this->_columnsToRepeatAtLeft = array('', ''); $this->_rowsToRepeatAtTop = array(0, 0); $this->_horizontalCentered = false; $this->_verticalCentered = false; $this->_printArea = null; + $this->_firstPageNumber = null; } /** @@ -328,20 +345,44 @@ class PHPExcel_Worksheet_PageSetup * This setting is overridden when fitToWidth and/or fitToHeight are in use * * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so scaling applies rather than fitToHeight / fitToWidth * @throws Exception * @return PHPExcel_Worksheet_PageSetup */ - public function setScale($pValue = 100) { + public function setScale($pValue = 100, $pUpdate = true) { // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, // but it is apparently still able to handle any scale >= 0, where 0 results in 100 if (($pValue >= 0) || is_null($pValue)) { $this->_scale = $pValue; + if ($pUpdate) { + $this->_fitToPage = false; + } } else { throw new Exception("Scale must not be negative"); } return $this; } + /** + * Get Fit To Page + * + * @return boolean + */ + public function getFitToPage() { + return $this->_fitToPage; + } + + /** + * Set Fit To Page + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToPage($pValue = true) { + $this->_fitToPage = $pValue; + return $this; + } + /** * Get Fit To Height * @@ -355,11 +396,13 @@ class PHPExcel_Worksheet_PageSetup * Set Fit To Height * * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling * @return PHPExcel_Worksheet_PageSetup */ - public function setFitToHeight($pValue = 1) { - if ($pValue != '') { - $this->_fitToHeight = $pValue; + public function setFitToHeight($pValue = 1, $pUpdate = true) { + $this->_fitToHeight = $pValue; + if ($pUpdate) { + $this->_fitToPage = true; } return $this; } @@ -377,11 +420,13 @@ class PHPExcel_Worksheet_PageSetup * Set Fit To Width * * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling * @return PHPExcel_Worksheet_PageSetup */ - public function setFitToWidth($pValue = 1) { - if ($pValue != '') { - $this->_fitToWidth = $pValue; + public function setFitToWidth($pValue = 1, $pUpdate = true) { + $this->_fitToWidth = $pValue; + if ($pUpdate) { + $this->_fitToPage = true; } return $this; } @@ -543,7 +588,7 @@ class PHPExcel_Worksheet_PageSetup } /** - * Set print area + * Set print area. E.g. 'A1:D10' or 'A1:D10,G5:M20' * * @param string $value * @throws Exception @@ -573,6 +618,35 @@ class PHPExcel_Worksheet_PageSetup { return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2); } + + /** + * Get first page number + * + * @return int + */ + public function getFirstPageNumber() { + return $this->_firstPageNumber; + } + + /** + * Set first page number + * + * @param int $value + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstPageNumber($value = null) { + $this->_firstPageNumber = $value; + return $this; + } + + /** + * Reset first page number + * + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function resetFirstPageNumber() { + return $this->setFirstPageNumber(null); + } /** * Implement PHP __clone to create a deep clone, not just a shallow copy. diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php b/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php index 1116c56da..d87c208e0 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Protection.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PasswordHasher.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Protection { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/Row.php b/libraries/PHPExcel/PHPExcel/Worksheet/Row.php index 1aa46cd08..d2105cb10 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/Row.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/Row.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -51,7 +51,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/CellIterator.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Row { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php b/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php index 76cc13249..e956c2424 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/RowDimension.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_RowDimension { @@ -71,7 +71,14 @@ class PHPExcel_Worksheet_RowDimension * @var bool */ private $_collapsed; - + + /** + * Index to cellXf. Null value means row has no explicit cellXf format. + * + * @var int|null + */ + private $_xfIndex; + /** * Create a new PHPExcel_Worksheet_RowDimension * @@ -85,6 +92,9 @@ class PHPExcel_Worksheet_RowDimension $this->_visible = true; $this->_outlineLevel = 0; $this->_collapsed = false; + + // set row dimension as unformatted by default + $this->_xfIndex = null; } /** @@ -193,7 +203,29 @@ class PHPExcel_Worksheet_RowDimension $this->_collapsed = $pValue; return $this; } - + + /** + * Get index to cellXf + * + * @return int + */ + public function getXfIndex() + { + return $this->_xfIndex; + } + + /** + * Set index to cellXf + * + * @param int $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setXfIndex($pValue = 0) + { + $this->_xfIndex = $pValue; + return $this; + } + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php b/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php index 459b6d07b..58b0dcaf4 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/RowIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -51,7 +51,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet/Row.php'; * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_RowIterator extends IteratorIterator { diff --git a/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php b/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php index 642595f64..684ef8a21 100644 --- a/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php +++ b/libraries/PHPExcel/PHPExcel/Worksheet/SheetView.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_SheetView { diff --git a/libraries/PHPExcel/PHPExcel/WorksheetIterator.php b/libraries/PHPExcel/PHPExcel/WorksheetIterator.php index 9edcc311f..57f0d5c45 100644 --- a/libraries/PHPExcel/PHPExcel/WorksheetIterator.php +++ b/libraries/PHPExcel/PHPExcel/WorksheetIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -48,7 +48,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_WorksheetIterator extends IteratorIterator { diff --git a/libraries/PHPExcel/PHPExcel/Writer/CSV.php b/libraries/PHPExcel/PHPExcel/Writer/CSV.php index 76b64f251..fd29f1559 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/CSV.php +++ b/libraries/PHPExcel/PHPExcel/Writer/CSV.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { /** diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php index 151fc1e47..81b00922a 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -94,7 +94,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel2007/Comments.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php index e7ef3d667..7b559f569 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Comments.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -67,7 +67,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_WriterPart { @@ -107,14 +107,14 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $objWriter->startElement('comments'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); - // Loop trough authors + // Loop through authors $objWriter->startElement('authors'); foreach ($authors as $author => $index) { $objWriter->writeElement('author', $author); } $objWriter->endElement(); - // Loop trough comments + // Loop through comments $objWriter->startElement('commentList'); foreach ($comments as $key => $value) { $this->_writeComment($objWriter, $key, $value, $authors); @@ -212,7 +212,7 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write $objWriter->endElement(); - // Loop trough comments + // Loop through comments foreach ($comments as $key => $value) { $this->_writeVMLComment($objWriter, $key, $value); } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php index ebe7d0f47..17505f5e0 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/ContentTypes.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php index fcd845906..3046cb5ce 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/DocProps.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php index f7d9f9895..584c65d89 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -70,7 +70,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_WriterPart { @@ -99,7 +99,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing'); $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); - // Loop trough images and write drawings + // Loop through images and write drawings $i = 1; $iterator = $pWorksheet->getDrawingCollection()->getIterator(); while ($iterator->valid()) { @@ -469,7 +469,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer $objWriter->endElement(); - // Loop trough images + // Loop through images foreach ($images as $key => $value) { $this->_writeVMLHeaderFooterImage($objWriter, $key, $value); } @@ -535,10 +535,10 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer // Get an array of all drawings $aDrawings = array(); - // Loop trough PHPExcel + // Loop through PHPExcel $sheetCount = $pPHPExcel->getSheetCount(); for ($i = 0; $i < $sheetCount; ++$i) { - // Loop trough images and add to array + // Loop through images and add to array $iterator = $pPHPExcel->getSheet($i)->getDrawingCollection()->getIterator(); while ($iterator->valid()) { $aDrawings[] = $iterator->current(); diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php index fd8ad849e..ba81c1be5 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Rels.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPart { @@ -219,13 +219,13 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar // Write hyperlink relationships? $i = 1; - foreach ($pWorksheet->getCellCollection() as $cell) { - if ($cell->hasHyperlink() && !$cell->getHyperlink()->isInternal()) { + foreach ($pWorksheet->getHyperlinkCollection() as $hyperlink) { + if (!$hyperlink->isInternal()) { $this->_writeRelationship( $objWriter, '_hyperlink_' . $i, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', - $cell->getHyperlink()->getUrl(), + $hyperlink->getUrl(), 'External' ); @@ -292,7 +292,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar $objWriter->startElement('Relationships'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Loop trough images and write relationships + // Loop through images and write relationships $i = 1; $iterator = $pWorksheet->getDrawingCollection()->getIterator(); while ($iterator->valid()) { @@ -341,7 +341,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar $objWriter->startElement('Relationships'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); - // Loop trough images and write relationships + // Loop through images and write relationships foreach ($pWorksheet->getHeaderFooter()->getImages() as $key => $value) { // Write relationship for image drawing $this->_writeRelationship( diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php index f1bc7168f..1e67d932d 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/StringTable.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -55,7 +55,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_WriterPart { @@ -83,7 +83,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // Fill index array $aFlippedStringTable = $this->flipStringTable($aStringTable); - // Loop trough cells + // Loop through cells $cellCollection = $pSheet->getCellCollection(); foreach ($cellCollection as $cell) { if (!is_object($cell->getValue()) && @@ -137,7 +137,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); $objWriter->writeAttribute('uniqueCount', count($pStringTable)); - // Loop trough string table + // Loop through string table foreach ($pStringTable as $textElement) { $objWriter->startElement('si'); @@ -174,7 +174,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr */ public function writeRichText(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_RichText $pRichText = null) { - // Loop trough rich text elements + // Loop through rich text elements $elements = $pRichText->getRichTextElements(); foreach ($elements as $element) { // r @@ -237,7 +237,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // t $objWriter->startElement('t'); $objWriter->writeAttribute('xml:space', 'preserve'); - $objWriter->writeRaw(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( htmlspecialchars($element->getText()) )); + $objWriter->writeRaw(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); $objWriter->endElement(); $objWriter->endElement(); @@ -254,7 +254,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // Return value $returnValue = array(); - // Loop trough stringtable and add flipped items to $returnValue + // Loop through stringtable and add flipped items to $returnValue foreach ($stringTable as $key => $value) { if (! $value instanceof PHPExcel_RichText) { $returnValue[$value] = $key; diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php index eca0ac781..8a41a6f35 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Style.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -79,7 +79,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPart { @@ -396,6 +396,10 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->writeAttribute('diagonalUp', 'false'); $objWriter->writeAttribute('diagonalDown', 'true'); break; + case PHPExcel_Style_Borders::DIAGONAL_BOTH: + $objWriter->writeAttribute('diagonalUp', 'true'); + $objWriter->writeAttribute('diagonalDown', 'true'); + break; } // BorderPr diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php index cd8c2c932..cf4565c78 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Theme.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -52,7 +52,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php index 7bf7f2454..727a5d32f 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Workbook.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_WriterPart { @@ -244,7 +244,8 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write $objWriter, $pPHPExcel->getSheet($i)->getTitle(), ($i + 1), - ($i + 1 + 3) + ($i + 1 + 3), + $pPHPExcel->getSheet($i)->getSheetState() ); } @@ -258,15 +259,19 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param string $pSheetname Sheet name * @param int $pSheetId Sheet id * @param int $pRelId Relationship ID + * @param string $sheetState Sheet state (visible, hidden, veryHidden) * @throws Exception */ - private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1) + private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible') { if ($pSheetname != '') { // Write sheet $objWriter->startElement('sheet'); $objWriter->writeAttribute('name', $pSheetname); $objWriter->writeAttribute('sheetId', $pSheetId); + if ($sheetState != 'visible' && $sheetState != '') { + $objWriter->writeAttribute('state', $sheetState); + } $objWriter->writeAttribute('r:id', 'rId' . $pRelId); $objWriter->endElement(); } else { @@ -449,11 +454,15 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write // Print area $printArea = PHPExcel_Cell::splitRange($pSheet->getPageSetup()->getPrintArea()); - $printArea = $printArea[0]; - $printArea[0] = PHPExcel_Cell::absoluteCoordinate($printArea[0]); - $printArea[1] = PHPExcel_Cell::absoluteCoordinate($printArea[1]); - $objWriter->writeRaw('\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printArea)); + $chunks = array(); + foreach ($printArea as $printAreaRect) { + $printAreaRect[0] = PHPExcel_Cell::absoluteCoordinate($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::absoluteCoordinate($printAreaRect[1]); + $chunks[] = '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printAreaRect); + } + + $objWriter->writeRaw(implode(',', $chunks)); $objWriter->endElement(); } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php index 45296cbfc..30fdc5f87 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -73,7 +73,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/XMLWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_WriterPart { @@ -190,6 +190,13 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->startElement('sheetPr'); //$objWriter->writeAttribute('codeName', $pSheet->getTitle()); + // tabColor + if ($pSheet->isTabColorSet()) { + $objWriter->startElement('tabColor'); + $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB()); + $objWriter->endElement(); + } + // outlinePr $objWriter->startElement('outlinePr'); $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0')); @@ -197,7 +204,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->endElement(); // pageSetUpPr - if (!is_null($pSheet->getPageSetup()->getFitToHeight()) || !is_null($pSheet->getPageSetup()->getFitToWidth())) { + if ($pSheet->getPageSetup()->getFitToPage()) { $objWriter->startElement('pageSetUpPr'); $objWriter->writeAttribute('fitToPage', '1'); $objWriter->endElement(); @@ -286,8 +293,8 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Selection $objWriter->startElement('selection'); - $objWriter->writeAttribute('activeCell', $pSheet->getSelectedCell()); - $objWriter->writeAttribute('sqref', $pSheet->getSelectedCell()); + $objWriter->writeAttribute('activeCell', $pSheet->getActiveCell()); + $objWriter->writeAttribute('sqref', $pSheet->getSelectedCells()); $objWriter->endElement(); $objWriter->endElement(); @@ -351,66 +358,59 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ private function _writeCols(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { // cols - $objWriter->startElement('cols'); + if (count($pSheet->getColumnDimensions()) > 0) { + $objWriter->startElement('cols'); - // Check if there is at least one column dimension specified. If not, create one. - if (count($pSheet->getColumnDimensions()) == 0) { - if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) { - $pSheet->getColumnDimension('A')->setWidth($pSheet->getDefaultColumnDimension()->getWidth()); - } else { - $pSheet->getColumnDimension('A')->setWidth(9.10); - } - } + $pSheet->calculateColumnWidths(); - $pSheet->calculateColumnWidths(); + // Loop through column dimensions + foreach ($pSheet->getColumnDimensions() as $colDimension) { + // col + $objWriter->startElement('col'); + $objWriter->writeAttribute('min', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + $objWriter->writeAttribute('max', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); - // Loop trough column dimensions - foreach ($pSheet->getColumnDimensions() as $colDimension) { - // col - $objWriter->startElement('col'); - $objWriter->writeAttribute('min', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); - $objWriter->writeAttribute('max', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + if ($colDimension->getWidth() < 0) { + // No width set, apply default of 10 + $objWriter->writeAttribute('width', '9.10'); + } else { + // Width set + $objWriter->writeAttribute('width', PHPExcel_Shared_String::FormatNumber($colDimension->getWidth())); + } - if ($colDimension->getWidth() < 0) { - // No width set, apply default of 10 - $objWriter->writeAttribute('width', '9.10'); - } else { - // Width set - $objWriter->writeAttribute('width', PHPExcel_Shared_String::FormatNumber($colDimension->getWidth())); + // Column visibility + if ($colDimension->getVisible() == false) { + $objWriter->writeAttribute('hidden', 'true'); + } + + // Auto size? + if ($colDimension->getAutoSize()) { + $objWriter->writeAttribute('bestFit', 'true'); + } + + // Custom width? + if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) { + $objWriter->writeAttribute('customWidth', 'true'); + } + + // Collapsed + if ($colDimension->getCollapsed() == true) { + $objWriter->writeAttribute('collapsed', 'true'); + } + + // Outline level + if ($colDimension->getOutlineLevel() > 0) { + $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel()); + } + + // Style + $objWriter->writeAttribute('style', $colDimension->getXfIndex()); + + $objWriter->endElement(); } - // Column visibility - if ($colDimension->getVisible() == false) { - $objWriter->writeAttribute('hidden', 'true'); - } - - // Auto size? - if ($colDimension->getAutoSize()) { - $objWriter->writeAttribute('bestFit', 'true'); - } - - // Custom width? - if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) { - $objWriter->writeAttribute('customWidth', 'true'); - } - - // Collapsed - if ($colDimension->getCollapsed() == true) { - $objWriter->writeAttribute('collapsed', 'true'); - } - - // Outline level - if ($colDimension->getOutlineLevel() > 0) { - $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel()); - } - - // Style - $objWriter->writeAttribute('style', 0); - - $objWriter->endElement(); - } - - $objWriter->endElement(); + $objWriter->endElement(); + } } /** @@ -460,7 +460,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Conditional id $id = 1; - // Loop trough styles in the current worksheet + // Loop through styles in the current worksheet foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { foreach ($conditionalStyles as $conditional) { // WHY was this again? @@ -491,7 +491,23 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('text', $conditional->getText()); } - if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS + if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_CONTAINSTEXT + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BEGINSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_ENDSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_NOTCONTAINS + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION) { foreach ($conditional->getConditions() as $formula) { @@ -517,20 +533,15 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ */ private function _writeDataValidations(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { - // Build a temporary array of datavalidation objects - $aDataValidations = array(); - foreach ($pSheet->getCellCollection() as $cell) { - if ($cell->hasDataValidation()) { - $aDataValidations[] = $cell->getDataValidation(); - } - } + // Datavalidation collection + $dataValidationCollection = $pSheet->getDataValidationCollection(); // Write data validations? - if (count($aDataValidations) > 0) { + if (count($dataValidationCollection) > 0) { $objWriter->startElement('dataValidations'); - $objWriter->writeAttribute('count', count($aDataValidations)); + $objWriter->writeAttribute('count', count($dataValidationCollection)); - foreach ($aDataValidations as $dv) { + foreach ($dataValidationCollection as $coordinate => $dv) { $objWriter->startElement('dataValidation'); if ($dv->getType() != '') { @@ -563,7 +574,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('prompt', $dv->getPrompt()); } - $objWriter->writeAttribute('sqref', $dv->getParent()->getCoordinate()); + $objWriter->writeAttribute('sqref', $coordinate); if ($dv->getFormula1() !== '') { $objWriter->writeElement('formula1', $dv->getFormula1()); @@ -588,25 +599,20 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ */ private function _writeHyperlinks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { - // Build a temporary array of hyperlink objects - $aHyperlinks = array(); - foreach ($pSheet->getCellCollection() as $cell) { - if ($cell->hasHyperlink()) { - $aHyperlinks[] = $cell->getHyperlink(); - } - } + // Hyperlink collection + $hyperlinkCollection = $pSheet->getHyperlinkCollection(); // Relation ID $relationId = 1; // Write hyperlinks? - if (count($aHyperlinks) > 0) { + if (count($hyperlinkCollection) > 0) { $objWriter->startElement('hyperlinks'); - foreach ($aHyperlinks as $hyperlink) { + foreach ($hyperlinkCollection as $coordinate => $hyperlink) { $objWriter->startElement('hyperlink'); - $objWriter->writeAttribute('ref', $hyperlink->getParent()->getCoordinate()); + $objWriter->writeAttribute('ref', $coordinate); if (!$hyperlink->isInternal()) { $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId); ++$relationId; @@ -755,17 +761,21 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation()); if (!is_null($pSheet->getPageSetup()->getScale())) { - $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale()); + $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale()); } if (!is_null($pSheet->getPageSetup()->getFitToHeight())) { - $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight()); + $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight()); } else { - $objWriter->writeAttribute('fitToHeight', '0'); + $objWriter->writeAttribute('fitToHeight', '0'); } if (!is_null($pSheet->getPageSetup()->getFitToWidth())) { - $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth()); + $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth()); } else { - $objWriter->writeAttribute('fitToWidth', '0'); + $objWriter->writeAttribute('fitToWidth', '0'); + } + if (!is_null($pSheet->getPageSetup()->getFirstPageNumber())) { + $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber()); + $objWriter->writeAttribute('useFirstPageNumber', '1'); } $objWriter->endElement(); @@ -876,7 +886,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Highest row number $highestRow = $pSheet->getHighestRow(); - // Loop trough cells + // Loop through cells $cellCollection = $pSheet->getCellCollection(); $cellsByRow = array(); @@ -887,13 +897,14 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ for ($currentRow = 1; $currentRow <= $highestRow; ++$currentRow) { // Get row dimension $rowDimension = $pSheet->getRowDimension($currentRow); - + // Write current row? $writeCurrentRow = isset($cellsByRow[$currentRow]) || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() == false || $rowDimension->getCollapsed() == true || - $rowDimension->getOutlineLevel() > 0; + $rowDimension->getOutlineLevel() > 0 || + $rowDimension->getXfIndex() !== null; if ($writeCurrentRow) { // Start a new row @@ -922,6 +933,12 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel()); } + // Style + if ($rowDimension->getXfIndex() !== null) { + $objWriter->writeAttribute('s', $rowDimension->getXfIndex()); + $objWriter->writeAttribute('customFormat', '1'); + } + // Write cells if (isset($cellsByRow[$currentRow])) { foreach($cellsByRow[$currentRow] as $cell) { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php index 473a813da..c09d05a19 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel2007/WriterPart.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,7 +43,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ abstract class PHPExcel_Writer_Excel2007_WriterPart { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5.php index abc9c655b..050e066f8 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -43,6 +43,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Cell.php'; /** PHPExcel_HashTable */ require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; +/** PHPExcel_Shared_File */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; + /** PHPExcel_Shared_OLE_PPS_Root */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/OLE/OLE_Root.php'; @@ -61,10 +64,17 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Workbook.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter { + /** + * Pre-calculate formulas + * + * @var boolean + */ + private $_preCalculateFormulas; + /** * PHPExcel object * @@ -107,6 +117,13 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter */ private $_str_table; + /** + * Color cache. Mapping between RGB value and color index. + * + * @var array + */ + private $_colors; + /** * Formula parser * @@ -121,9 +138,10 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter * @param PHPExcel $phpExcel PHPExcel object */ public function __construct(PHPExcel $phpExcel) { + $this->_preCalculateFormulas = true; $this->_phpExcel = $phpExcel; $this->_BIFF_version = 0x0600; - $this->_tempDir = ''; + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); $this->_str_total = 0; $this->_str_unique = 0; @@ -151,9 +169,12 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + // initialize colors array + $this->_colors = array(); + // Initialise workbook writer $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, $this->_BIFF_version, - $this->_str_total, $this->_str_unique, $this->_str_table, $this->_parser, $this->_tempDir); + $this->_str_total, $this->_str_unique, $this->_str_table, $this->_colors, $this->_parser, $this->_tempDir); // Initialise worksheet writers $countSheets = count($this->_phpExcel->getAllSheets()); @@ -162,8 +183,9 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $writerWorksheet = new PHPExcel_Writer_Excel5_Worksheet($this->_BIFF_version, $this->_str_total, $this->_str_unique, - $this->_str_table, + $this->_str_table, $this->_colors, $this->_parser, $this->_tempDir, + $this->_preCalculateFormulas, $phpSheet); $this->_writerWorksheets[$i] = $writerWorksheet; } @@ -248,4 +270,22 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter return $this; } + /** + * Get Pre-Calculate Formulas + * + * @return boolean + */ + public function getPreCalculateFormulas() { + return $this->_preCalculateFormulas; + } + + /** + * Set Pre-Calculate Formulas + * + * @param boolean $pValue Pre-Calculate Formulas? + */ + public function setPreCalculateFormulas($pValue = true) { + $this->_preCalculateFormulas = $pValue; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php index befcc88f6..b293ddeeb 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/BIFFwriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_BIFFwriter (used as the base for this class): @@ -65,7 +65,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_BIFFwriter { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php index b2d8d074b..4d5f22bd1 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Escher { @@ -395,7 +395,7 @@ class PHPExcel_Writer_Excel5_Escher $header = pack('vvV', $recVerInstance, $recType, $length); - $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0xA000); + $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00); // the options @@ -447,7 +447,7 @@ class PHPExcel_Writer_Excel5_Escher // end offsetY $endOffsetY = $this->_object->getEndOffsetY(); - $clientAnchorData = pack('vvvvvvvvv', 0x00, + $clientAnchorData = pack('vvvvvvvvv', 0x02, $c1, $startOffsetX, $r1, $startOffsetY, $c2, $endOffsetX, $r2, $endOffsetY); diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php index 6f5194054..97a553140 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -46,7 +46,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Font { diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php index b436a4f0f..116513d45 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Parser.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Parser (used as the base for this class): @@ -70,7 +70,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/BIFFwriter.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Parser { @@ -533,12 +533,12 @@ class PHPExcel_Writer_Excel5_Parser } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) { return $this->_convertRef2d($token); - // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 - } elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z](\d+)$/u",$token)) { + // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1 + } elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { return $this->_convertRef3d($token); - // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 - } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z](\d+)$/u",$token)) { + // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1 + } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { return $this->_convertRef3d($token); // match ranges like A1:B2 @@ -549,12 +549,12 @@ class PHPExcel_Writer_Excel5_Parser } elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/",$token)) { return $this->_convertRange2d($token); - // match external ranges like Sheet1!A1 or Sheet1:Sheet2!A1:B2 - } elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/u",$token)) { + // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + } elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { return $this->_convertRange3d($token); - // match external ranges like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1:B2 - } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/u",$token)) { + // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + } elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { return $this->_convertRange3d($token); // operators (including parentheses) @@ -652,9 +652,9 @@ class PHPExcel_Writer_Excel5_Parser // TODO: possible class value 0,1,2 check Formula.pm // Split the range into 2 cell refs if (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\:([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) { - list($cell1, $cell2) = split(':', $range); + list($cell1, $cell2) = explode(':', $range); } elseif (preg_match("/^([A-Ia-i]?[A-Za-z])(\d+)\.\.([A-Ia-i]?[A-Za-z])(\d+)$/", $range)) { - list($cell1, $cell2) = split('\.\.', $range); + list($cell1, $cell2) = explode('..', $range); } else { // TODO: use real error codes @@ -694,7 +694,7 @@ class PHPExcel_Writer_Excel5_Parser $class = 2; // as far as I know, this is magick. // Split the ref at the ! symbol - list($ext_ref, $range) = split('!', $token); + list($ext_ref, $range) = explode('!', $token); // Convert the external reference part (different for BIFF8) if ($this->_BIFF_version == 0x0500) { @@ -704,10 +704,10 @@ class PHPExcel_Writer_Excel5_Parser } // Split the range into 2 cell refs - list($cell1, $cell2) = split(':', $range); + list($cell1, $cell2) = explode(':', $range); // Convert the cell references - if (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/", $cell1)) { + if (preg_match("/^(\\$)?[A-Ia-i]?[A-Za-z](\\$)?(\d+)$/", $cell1)) { $cell_array1 = $this->_cellToPackedRowcol($cell1); list($row1, $col1) = $cell_array1; $cell_array2 = $this->_cellToPackedRowcol($cell2); @@ -773,7 +773,7 @@ class PHPExcel_Writer_Excel5_Parser $class = 2; // as far as I know, this is magick. // Split the ref at the ! symbol - list($ext_ref, $cell) = split('!', $cell); + list($ext_ref, $cell) = explode('!', $cell); // Convert the external reference part (different for BIFF8) if ($this->_BIFF_version == 0x0500) { @@ -814,7 +814,7 @@ class PHPExcel_Writer_Excel5_Parser // Check if there is a sheet range eg., Sheet1:Sheet2. if (preg_match("/:/", $ext_ref)) { - list($sheet_name1, $sheet_name2) = split(':', $ext_ref); + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); $sheet1 = $this->_getSheetIndex($sheet_name1); if ($sheet1 == -1) { @@ -859,7 +859,7 @@ class PHPExcel_Writer_Excel5_Parser // Check if there is a sheet range eg., Sheet1:Sheet2. if (preg_match("/:/", $ext_ref)) { - list($sheet_name1, $sheet_name2) = split(':', $ext_ref); + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); $sheet1 = $this->_getSheetIndex($sheet_name1); if ($sheet1 == -1) { @@ -1158,47 +1158,47 @@ class PHPExcel_Writer_Excel5_Parser default: // if it's a reference if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and - !ereg("[0-9]",$this->_lookahead) and + !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.') and ($this->_lookahead != '!')) { return $token; } - // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1) - elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead) and + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.')) { return $token; } // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z][0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead) and + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and ($this->_lookahead != ':') and ($this->_lookahead != '.')) { return $token; } // if it's a range (A1:A2) elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and - !ereg("[0-9]",$this->_lookahead)) + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } // if it's a range (A1..A2) elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and - !ereg("[0-9]",$this->_lookahead)) + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } - // If it's an external range like Sheet1!A1 or Sheet1:Sheet2!A1:B2 - elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead)) + // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } - // If it's an external range like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1:B2 - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$token) and - !ereg("[0-9]",$this->_lookahead)) + // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) { return $token; } @@ -1210,12 +1210,12 @@ class PHPExcel_Writer_Excel5_Parser return $token; } // If it's a string (of maximum 255 characters) - elseif (ereg("^\"[^\"]{0,255}\"$",$token)) + elseif (preg_match("/^\"[^\"]{0,255}\"$/",$token)) { return $token; } // if it's a function call - elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$token) and ($this->_lookahead == "(")) + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "(")) { return $token; } @@ -1291,7 +1291,7 @@ class PHPExcel_Writer_Excel5_Parser function _expression() { // If it's a string return a string node - if (ereg("^\"[^\"]{0,255}\"$", $this->_current_token)) { + if (preg_match("/^\"[^\"]{0,255}\"$/", $this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; @@ -1388,21 +1388,21 @@ class PHPExcel_Writer_Excel5_Parser $this->_advance(); return $result; } - // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1) - elseif (preg_match("/^\w+(\:\w+)?\![A-Ia-i]?[A-Za-z][0-9]+$/u",$this->_current_token)) + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^\w+(\:\w+)?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } - // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\![A-Ia-i]?[A-Za-z][0-9]+$/u",$this->_current_token)) + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) { $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } - // if it's a range + // if it's a range A1:B2 or $A$1:$B$2 elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token) or preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token)) { @@ -1410,17 +1410,21 @@ class PHPExcel_Writer_Excel5_Parser $this->_advance(); return $result; } - // If it's an external range (Sheet1!A1 or Sheet1!A1:B2) - elseif (preg_match("/^\w+(\:\w+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$this->_current_token)) + // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2) + elseif (preg_match("/^\w+(\:\w+)?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) { - $result = $this->_current_token; + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } - // If it's an external range ('Sheet1'!A1 or 'Sheet1'!A1:B2) - elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/u",$this->_current_token)) + // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2) + elseif (preg_match("/^'[\w -]+(\:[\w -]+)?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) { - $result = $this->_current_token; + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); $this->_advance(); return $result; } @@ -1431,7 +1435,7 @@ class PHPExcel_Writer_Excel5_Parser return $result; } // if it's a function call - elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$this->_current_token)) + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token)) { $result = $this->_func(); return $result; diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php index ba359d311..bdae49f5c 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Workbook.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Workbook (used as the base for this class): @@ -90,6 +90,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContaine /** PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php'; +/** PHPExcel_Worksheet */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Worksheet.php'; + /** PHPExcel_Writer_Excel5_Xf */ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Xf.php'; @@ -111,7 +114,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Escher.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter { @@ -165,11 +168,6 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter */ private $_phpExcel; - /** - * Color cache - */ - private $_colors = array(); - /** * Fonts writers * @@ -233,6 +231,11 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter */ private $_str_table; + /** + * Color cache + */ + private $_colors; + /** * Class constructor @@ -246,7 +249,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter */ public function __construct(PHPExcel $phpExcel = null, $BIFF_version = 0x0600, &$str_total, - &$str_unique, &$str_table, $parser, $tempDir = '' + &$str_unique, &$str_table, &$colors, $parser, $tempDir = '' ) { // It needs to call its parent's constructor explicitly @@ -261,6 +264,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $this->_str_total = &$str_total; $this->_str_unique = &$str_unique; $this->_str_table = &$str_table; + $this->_colors = &$colors; $this->_setPaletteXl97(); $this->_tmp_dir = $tempDir; @@ -287,6 +291,18 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $this->_parser->_references[] = $ref; // Register reference with parser } } + + // Build color cache + + // Sheet tab colors? + $countSheets = count($phpExcel->getAllSheets()); + for ($i = 0; $i < $countSheets; ++$i) { + $phpSheet = $phpExcel->getSheet($i); + if ($phpSheet->isTabColorSet()) { + $this->_addColor($phpSheet->getTabColor()->getRGB()); + } + } + } /** @@ -302,13 +318,6 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $xfWriter->setBIFFVersion($this->_BIFF_version); $xfWriter->setIsStyleXf($isStyleXf); - $xfWriter->setFgColor($this->_addColor($style->getFill()->getStartColor()->getRGB())); - $xfWriter->setBgColor($this->_addColor($style->getFill()->getEndColor()->getRGB())); - $xfWriter->setBottomColor($this->_addColor($style->getBorders()->getBottom()->getColor()->getRGB())); - $xfWriter->setTopColor($this->_addColor($style->getBorders()->getTop()->getColor()->getRGB())); - $xfWriter->setRightColor($this->_addColor($style->getBorders()->getRight()->getColor()->getRGB())); - $xfWriter->setLeftColor($this->_addColor($style->getBorders()->getLeft()->getColor()->getRGB())); - // Add the font if not already added $fontHashCode = $style->getFont()->getHashCode(); @@ -329,6 +338,15 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // Assign the font index to the xf record $xfWriter->setFontIndex($fontIndex); + // Background colors, best to treat these after the font so black will come after white in custom palette + $xfWriter->setFgColor($this->_addColor($style->getFill()->getStartColor()->getRGB())); + $xfWriter->setBgColor($this->_addColor($style->getFill()->getEndColor()->getRGB())); + $xfWriter->setBottomColor($this->_addColor($style->getBorders()->getBottom()->getColor()->getRGB())); + $xfWriter->setTopColor($this->_addColor($style->getBorders()->getTop()->getColor()->getRGB())); + $xfWriter->setRightColor($this->_addColor($style->getBorders()->getRight()->getColor()->getRGB())); + $xfWriter->setLeftColor($this->_addColor($style->getBorders()->getLeft()->getColor()->getRGB())); + $xfWriter->setDiagColor($this->_addColor($style->getBorders()->getDiagonal()->getColor()->getRGB())); + // Add the number format if it is not a built-in one and not already added if ($style->getNumberFormat()->getBuiltInFormatCode() === false) { $numberFormatHashCode = $style->getNumberFormat()->getHashCode(); @@ -509,7 +527,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // Add part 2 of the Workbook globals, the SHEET records $this->_calcSheetOffsets(); for ($i = 0; $i < $total_worksheets; ++$i) { - $this->_storeBoundsheet($this->_phpExcel->getSheet($i)->getTitle(), $this->_worksheetOffsets[$i]); + $this->_storeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]); } // Add part 3 of the Workbook globals @@ -717,6 +735,34 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter { $chunk = ''; + // Named ranges + if (count($this->_phpExcel->getNamedRanges()) > 0) { + // Loop named ranges + $namedRanges = $this->_phpExcel->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + + // Create absolute coordinate + $range = PHPExcel_Cell::splitRange($namedRange->getRange()); + for ($i = 0; $i < count($range); $i++) { + $range[$i][0] = '\'' . str_replace("'", "''", $namedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteCoordinate($range[$i][0]); + if (isset($range[$i][1])) { + $range[$i][1] = PHPExcel_Cell::absoluteCoordinate($range[$i][1]); + } + } + $range = PHPExcel_Cell::buildRange($range); // e.g. Sheet1!$A$1:$B$2 + + // parse formula + try { + $error = $this->_parser->parse($range); + $formulaData = $this->_parser->toReversePolish(); + $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, 0, false)); + + } catch(Exception $e) { + // do nothing + } + } + } + // total number of sheets $total_worksheets = count($this->_phpExcel->getAllSheets()); @@ -775,19 +821,28 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // write the print areas, if any for ($i = 0; $i < $total_worksheets; ++$i) { if ($this->_phpExcel->getSheet($i)->getPageSetup()->isPrintAreaSet()) { - // Print area + // Print area, e.g. A3:J6,H1:X20 $printArea = PHPExcel_Cell::splitRange($this->_phpExcel->getSheet($i)->getPageSetup()->getPrintArea()); - $printArea = $printArea[0]; - $printArea[0] = PHPExcel_Cell::coordinateFromString($printArea[0]); - $printArea[1] = PHPExcel_Cell::coordinateFromString($printArea[1]); - - $print_rowmin = $printArea[0][1] - 1; - $print_rowmax = $printArea[1][1] - 1; - $print_colmin = PHPExcel_Cell::columnIndexFromString($printArea[0][0]) - 1; - $print_colmax = PHPExcel_Cell::columnIndexFromString($printArea[1][0]) - 1; + $countPrintArea = count($printArea); - // construct formula data manually because parser does not recognize absolute 3d cell references - $formulaData = pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); + $formulaData = ''; + for ($j = 0; $j < $countPrintArea; ++$j) { + $printAreaRect = $printArea[$j]; // e.g. A3:J6 + $printAreaRect[0] = PHPExcel_Cell::coordinateFromString($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::coordinateFromString($printAreaRect[1]); + + $print_rowmin = $printAreaRect[0][1] - 1; + $print_rowmax = $printAreaRect[1][1] - 1; + $print_colmin = PHPExcel_Cell::columnIndexFromString($printAreaRect[0][0]) - 1; + $print_colmax = PHPExcel_Cell::columnIndexFromString($printAreaRect[1][0]) - 1; + + // construct formula data manually because parser does not recognize absolute 3d cell references + $formulaData .= pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); + + if ($j > 0) { + $formulaData .= pack('C', 0x10); // list operator token ',' + } + } // store the DEFINEDNAME record $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x06), $formulaData, $i + 1, true)); @@ -886,21 +941,34 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Writes Excel BIFF BOUNDSHEET record. * - * @param string $sheetname Worksheet name + * @param PHPExcel_Worksheet $sheet Worksheet name * @param integer $offset Location of worksheet BOF * @access private */ - function _storeBoundsheet($sheetname,$offset) + function _storeBoundsheet($sheet, $offset) { + $sheetname = $sheet->getTitle(); $record = 0x0085; // Record identifier + + // sheet state + switch ($sheet->getSheetState()) { + case PHPExcel_Worksheet::SHEETSTATE_VISIBLE: $ss = 0x00; break; + case PHPExcel_Worksheet::SHEETSTATE_HIDDEN: $ss = 0x01; break; + case PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN: $ss = 0x02; break; + default: $ss = 0x00; break; + } + + // sheet type + $st = 0x00; + $grbit = 0x0000; // Visibility and sheet type if ($this->_BIFF_version == 0x0600) { - $data = pack("Vv", $offset, $grbit); + $data = pack("VCC", $offset, $ss, $st); $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheetname); } else { $cch = strlen($sheetname); // Length of sheet name - $data = pack("VvC", $offset, $grbit, $cch); + $data = pack("VCCC", $offset, $ss, $st, $cch); $data .= $sheetname; } diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php index 079947437..831740964 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class): @@ -69,6 +69,9 @@ if (!defined('PHPEXCEL_ROOT')) { define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); } +/** PHPExcel_Cell_DataType */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Cell/DataType.php'; + /** PHPExcel_Writer_Excel5_Parser.php */ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Parser.php'; @@ -81,6 +84,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5/Escher.php'; /** PHPExcel_RichText */ require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; +/** PHPExcel_Shared_Font */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Font.php'; + /** PHPExcel_Shared_String */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/String.php'; @@ -105,7 +111,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Escher/DgContainer/SpgrContainer/S * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter { @@ -194,6 +200,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter */ var $_str_table; + /** + * Color cache + */ + private $_colors; + /** * The temporary dir for storing files * @var string @@ -256,8 +267,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter */ public function __construct($BIFF_version, &$str_total, - &$str_unique, &$str_table, - $parser, $tempDir = '', $phpSheet) + &$str_unique, &$str_table, &$colors, + $parser, $tempDir = '', $preCalculateFormulas, $phpSheet) { // It needs to call its parent's constructor explicitly parent::__construct(); @@ -269,9 +280,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } + $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; @@ -378,12 +391,14 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Column dimensions $columnDimensions = $this->_phpSheet->getColumnDimensions(); for ($i = 0; $i < 256; ++$i) { - $width = 9.140625; // assuming Calibri 11 $hidden = 0; $level = 0; + $xfIndex = 15; // there are 15 cell style Xfs if ($this->_phpSheet->getDefaultColumnDimension()->getWidth() >= 0) { $width = $this->_phpSheet->getDefaultColumnDimension()->getWidth(); + } else { + $width = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($this->_phpSheet->getParent()->getDefaultStyle()->getFont()); } $columnLetter = PHPExcel_Cell::stringFromColumnIndex($i); @@ -394,9 +409,10 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } $hidden = $columnDimension->getVisible() ? 0 : 1; $level = $columnDimension->getOutlineLevel(); + $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs } - $this->_setColumn( $i, $i, $width, null, $hidden, $level); + $this->_setColumn( $i, $i, $width, $xfIndex, $hidden, $level); } // Write the COLINFO records if they exist @@ -472,12 +488,24 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Write sheet protection $this->_storeProtect(); + // Write SCENPROTECT + $this->_writeScenProtect(); + + // Write OBJECTPROTECT + $this->_writeObjectProtect(); + // Write sheet password $this->_storePassword(); // Write sheet dimensions $this->_storeDimensions(); + // Row dimensions + foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { + $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs + $this->_setRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); + } + // Write Cells foreach ($this->_phpSheet->getCellCollection() as $cell) { $row = $cell->getRow() - 1; @@ -505,7 +533,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter break; case PHPExcel_Cell_DataType::TYPE_FORMULA: - $this->_writeFormula($row, $column, $cell->getValue(), $xfIndex); + $calculatedValue = $this->_preCalculateFormulas ? + $cell->getCalculatedValue() : null; + $this->_writeFormula($row, $column, $cell->getValue(), $xfIndex, $calculatedValue); break; case PHPExcel_Cell_DataType::TYPE_BOOL: @@ -520,19 +550,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_writeNumber($row, $column, $cell->getValue(), $xfIndex); break; } - - // Hyperlink? - if ($cell->hasHyperlink()) { - $this->_writeUrl($row, $column, str_replace('sheet://', 'internal:', $cell->getHyperlink()->getUrl())); - } } } - // Row dimensions - foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { - $this->_setRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), null, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); - } - // Append if ($this->_BIFF_version == 0x0600) { $this->_storeMsoDrawing(); @@ -542,13 +562,40 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if ($this->_phpSheet->getFreezePane()) { $this->_storePanes(); } - $this->_storeSelection($this->_selection); + $this->_storeSelection(); $this->_storeMergedCells(); + + // Hyperlinks + if ($this->_BIFF_version == 0x0600) { + foreach ($this->_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 - 1, PHPExcel_Cell::columnIndexFromString($column) - 1, $url); + } + } + /*if ($this->_BIFF_version == 0x0600) { $this->_storeDataValidity(); }*/ if ($this->_BIFF_version == 0x0600) { + $this->_storeSheetLayout(); + $this->_writeSheetProtection(); $this->_storeRangeProtection(); } @@ -627,32 +674,18 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $firstcol first column on the range * @param integer $lastcol last column on the range * @param integer $width width to set - * @param mixed $format The optional XF format to apply to the columns + * @param integer $xfIndex The optional cell style Xf index to apply to the columns * @param integer $hidden The optional hidden atribute * @param integer $level The optional outline level */ - private function _setColumn($firstcol, $lastcol, $width, $format = null, $hidden = 0, $level = 0) + private function _setColumn($firstcol, $lastcol, $width, $xfIndex = 15, $hidden = 0, $level = 0) { - $this->_colinfo[] = array($firstcol, $lastcol, $width, &$format, $hidden, $level); + $this->_colinfo[] = array($firstcol, $lastcol, $width, $xfIndex, $hidden, $level); // Set width to zero if column is hidden $width = ($hidden) ? 0 : $width; } - /** - * Set which cell or cells are selected in a worksheet - * - * @access public - * @param integer $first_row first row in the selected quadrant - * @param integer $first_column first column in the selected quadrant - * @param integer $last_row last row in the selected quadrant - * @param integer $last_column last column in the selected quadrant - */ - function setSelection($first_row,$first_column,$last_row,$last_column) - { - $this->_selection = array($first_row,$first_column,$last_row,$last_column); - } - /** * Set the option to print the row and column headers on the printed page. * @@ -913,18 +946,56 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @param integer $col Zero indexed column * @param string $formula The formula text string * @param mixed $format The optional XF format + * @param mixed $calculatedValue Calculated value * @return integer */ - private function _writeFormula($row, $col, $formula, $xfIndex) + private function _writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) { $record = 0x0006; // Record identifier - // Excel normally stores the last calculated value of the formula in $num. - // Clearly we are not in a position to calculate this a priori. Instead - // we set $num to zero and set the option flags in $grbit to ensure - // automatic calculation of the formula when the file is opened. - // - $num = 0x00; // Current value of formula + // 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', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF); + + } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { + // Numeric value + $num = pack('d', $calculatedValue); + + } elseif (is_string($calculatedValue)) { + if (array_key_exists($calculatedValue, PHPExcel_Cell_DataType::getErrorCodes())) { + // Error value + $num = pack('CCCvCv', 0x02, 0x00, $this->_mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); + + } elseif ($calculatedValue === '' && $this->_BIFF_version == 0x0600) { + // Empty string (and BIFF8) + $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + + } else { + // Non-empty string value (or empty string BIFF5) + $stringValue = $calculatedValue; + $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + + } + + } 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 @@ -948,9 +1019,17 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $length = 0x16 + $formlen; // Length of the record data $header = pack("vv", $record, $length); - $data = pack("vvvdvVv", $row, $col, $xfIndex, $num, - $grbit, $unknown, $formlen); + + $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 (Exception $e) { @@ -959,6 +1038,22 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } + /** + * 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 @@ -1148,40 +1243,21 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // relative if link starts with up-dir, "..\..\somefile.xls" // otherwise, absolute - $absolute = 0x02; // Bit mask - if (!preg_match("/\\\/", $url)) { - $absolute = 0x00; - } - if (preg_match("/^\.\.\\\/", $url)) { - $absolute = 0x00; + $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) - /*if (preg_match("/\#/", $url)) { - list($dir_long, $sheet) = split("\#", $url); - } else { - $dir_long = $url; - } - - if (isset($sheet)) { - $link_type |= 0x08; - $sheet_len = pack("V", strlen($sheet) + 0x01); - $sheet = join("\0", split('', $sheet)); - $sheet .= "\0\0\0"; - } else { - $sheet_len = ''; - $sheet = ''; - }*/ $dir_long = $url; if (preg_match("/\#/", $url)) { $link_type |= 0x08; } - // Pack the link type $link_type = pack("V", $link_type); @@ -1193,7 +1269,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0"; // Store the long dir name as a wchar string (non-null terminated) - //$dir_long = join("\0", split('', $dir_long)); $dir_long = $dir_long . "\0"; // Pack the lengths of the dir strings @@ -1238,11 +1313,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * @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 mixed $format XF format we are giving to the row + * @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 _setRow($row, $height, $format = null, $hidden = false, $level = 0) + private function _setRow($row, $height, $xfIndex, $hidden = false, $level = 0) { $record = 0x0208; // Record identifier $length = 0x0010; // Number of bytes to follow @@ -1252,7 +1327,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $irwMac = 0x0000; // Used by Excel to optimise loading $reserved = 0x0000; // Reserved $grbit = 0x0000; // Option flags - $ixfe = 0x0F; // hard-coding XF index + $ixfe = $xfIndex; if ( $height < 0 ){ $height = null; @@ -1275,8 +1350,10 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if ($hidden) { $grbit |= 0x0020; } - $grbit |= 0x0040; // fUnsynced - if ($format) { + if ($height !== null) { + $grbit |= 0x0040; // fUnsynced + } + if ($xfIndex !== 0xF) { $grbit |= 0x0080; } $grbit |= 0x0100; @@ -1451,9 +1528,9 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $coldx = 8.43; } if (isset($col_array[3])) { - $format = $col_array[3]; + $xfIndex = $col_array[3]; } else { - $format = 0; + $xfIndex = 15; } if (isset($col_array[4])) { $grbit = $col_array[4]; @@ -1470,7 +1547,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $coldx *= 256; // Convert to units of 1/256 of a char - $ixfe = 0x0F; // hard-coding XF index + $ixfe = $xfIndex; $reserved = 0x00; // Reserved $level = max(0, min($level, 7)); @@ -1486,12 +1563,39 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter * Write BIFF record SELECTION. * * @access private - * @param array $array array containing ($rwFirst,$colFirst,$rwLast,$colLast) - * @see setSelection() */ - function _storeSelection($array) + function _storeSelection() { - list($rwFirst,$colFirst,$rwLast,$colLast) = $array; + // 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($colFirst, 255); + $colLast = min($colLast, 255); + if ($this->_BIFF_version == 0x0600) { + $rwFirst = min($rwFirst, 65535); + $rwLast = min($rwLast, 65535); + } else { + $rwFirst = min($rwFirst, 16383); + $rwLast = min($rwLast, 16383); + } + $record = 0x001D; // Record identifier $length = 0x000F; // Number of bytes to follow @@ -1585,6 +1689,77 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } } + /** + * Write SHEETLAYOUT record + */ + private function _storeSheetLayout() + { + 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 * @@ -2156,7 +2331,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if ($this->_phpSheet->getShowSummaryRight()) { $grbit |= 0x0080; // Outline summary right } - if ($this->_phpSheet->getPageSetup()->getFitToWidth() || $this->_phpSheet->getPageSetup()->getFitToHeight()) { + if ($this->_phpSheet->getPageSetup()->getFitToPage()) { $grbit |= 0x0100; // Page setup fit to page } if ($this->_outline_on) { @@ -2292,6 +2467,54 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $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. * diff --git a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php index 717866330..be8d11ad8 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Excel5/Xf.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Format (used as the base for this class): @@ -87,7 +87,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Protection.php'; * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Xf { @@ -234,7 +234,7 @@ class PHPExcel_Writer_Excel5_Xf if ($this->_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) == 0) { $this->_left_color = 0; } - if ($this->_diag == 0) { + if ($this->_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) == 0) { $this->_diag_color = 0; } @@ -302,15 +302,19 @@ class PHPExcel_Writer_Excel5_Xf $border1 |= $this->_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) << 12; $border1 |= $this->_left_color << 16; $border1 |= $this->_right_color << 23; - $diag_tl_to_rb = 0; - $diag_tr_to_lb = 0; + + $diagonalDirection = $this->_style->getBorders()->getDiagonalDirection(); + $diag_tl_to_rb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_DOWN; + $diag_tr_to_lb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_UP; $border1 |= $diag_tl_to_rb << 30; $border1 |= $diag_tr_to_lb << 31; $border2 = $this->_top_color; // Border color $border2 |= $this->_bottom_color << 7; $border2 |= $this->_diag_color << 14; - $border2 |= $this->_diag << 21; + $border2 |= $this->_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) << 21; $border2 |= $this->_mapFillType($this->_style->getFill()->getFillType()) << 26; $header = pack("vv", $record, $length); @@ -395,6 +399,17 @@ class PHPExcel_Writer_Excel5_Xf $this->_right_color = $colorIndex; } + /** + * Sets the cell's diagonal border color + * + * @access public + * @param int $colorIndex Color index + */ + function setDiagColor($colorIndex) + { + $this->_diag_color = $colorIndex; + } + /** * Sets the cell's foreground color diff --git a/libraries/PHPExcel/PHPExcel/Writer/HTML.php b/libraries/PHPExcel/PHPExcel/Writer/HTML.php index d1f59a1de..4ac8c73a6 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/HTML.php +++ b/libraries/PHPExcel/PHPExcel/Writer/HTML.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { /** @@ -111,11 +111,39 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { private $_columnWidths = null; /** - * Default font size + * Default font * - * @var int + * @var PHPExcel_Style_Font */ - private $_defaultFontSize; + private $_defaultFont; + + /** + * Flag whether spans have been calculated + * + * @var boolean + */ + private $_spansAreCalculated; + + /** + * Excel cells that should not be written as HTML cells + * + * @var array + */ + private $_isSpannedCell; + + /** + * Excel cells that are upper-left corner in a cell merge + * + * @var array + */ + private $_isBaseCell; + + /** + * Excel rows that should not be written as HTML rows + * + * @var array + */ + private $_isSpannedRow; /** * Is the current writer creating PDF? @@ -131,9 +159,14 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { */ public function __construct(PHPExcel $phpExcel) { $this->_phpExcel = $phpExcel; - $this->_defaultFontSize = $this->_phpExcel->getDefaultStyle()->getFont()->getSize(); + $this->_defaultFont = $this->_phpExcel->getDefaultStyle()->getFont(); $this->_sheetIndex = 0; $this->_imagesRoot = '.'; + + $this->_spansAreCalculated = false; + $this->_isSpannedCell = array(); + $this->_isBaseCell = array(); + $this->_isSpannedRow = array(); } /** @@ -210,6 +243,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { case PHPExcel_Style_Border::BORDER_NONE: return '0px'; case PHPExcel_Style_Border::BORDER_DASHED: return '1px dashed'; case PHPExcel_Style_Border::BORDER_DOTTED: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DOUBLE: return '3px double'; case PHPExcel_Style_Border::BORDER_THICK: return '2px solid'; default: return '1px solid'; // map others to thin } @@ -286,6 +320,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { throw new Exception('Internal PHPExcel object not set to an instance of an object.'); } + // Ensure that Spans have been calculated? + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + // Fetch sheets $sheets = array(); if (is_null($this->_sheetIndex)) { @@ -300,9 +339,6 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Loop all sheets $sheetId = 0; foreach ($sheets as $sheet) { - // Get cell collection - $cellCollection = $sheet->getCellCollection(); - // Write table header $html .= $this->_generateTableHeader($sheet); @@ -313,13 +349,13 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; - // Loop trough cells + // Loop through cells $rowData = null; for ($row = $dimension[0][1]; $row <= $dimension[1][1]; ++$row) { // Start a new row $rowData = array(); - // Loop trough columns + // Loop through columns for ($column = $dimension[0][0]; $column <= $dimension[1][0]; ++$column) { // Cell exists? if ($sheet->cellExistsByColumnAndRow($column, $row)) { @@ -329,8 +365,10 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { } } - // Write row - $html .= $this->_generateRow($sheet, $rowData, $row - 1); + // Write row if there are HTML table cells in it + if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) { + $html .= $this->_generateRow($sheet, $rowData, $row - 1); + } } // Write table footer @@ -455,6 +493,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $this->_cssStyles; } + // Ensure that spans have been calculated + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + // Construct CSS $css = array(); @@ -523,7 +566,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // col elements, loop through columnDimensions and set width foreach ($sheet->getColumnDimensions() as $columnDimension) { - if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFontSize)) >= 0) { + if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) { $width = PHPExcel_Shared_Drawing::pixelsToPoints($width); $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1; $this->_columnWidths[$sheetIndex][$column] = $width; @@ -542,7 +585,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // table.sheetN tr { } $css['table.sheet' . $sheetIndex . ' tr'] = array(); - $pt_height = $rowDimension->getRowHeight(); + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt'; if ($rowDimension->getVisible() === false) { $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; @@ -556,7 +603,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // table.sheetN tr.rowYYYYYY { } $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array(); - $pt_height = $rowDimension->getRowHeight(); + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt'; if ($rowDimension->getVisible() === false) { $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none'; @@ -822,7 +873,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Value if ($cell->getValue() instanceof PHPExcel_RichText) { - // Loop trough rich text elements + // Loop through rich text elements $elements = $cell->getValue()->getRichTextElements(); foreach ($elements as $element) { // Rich text start? @@ -854,17 +905,16 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { if ($this->_preCalculateFormulas) { $cellData = PHPExcel_Style_NumberFormat::toFormattedString( $cell->getCalculatedValue(), - $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode() + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') ); } else { $cellData = PHPExcel_Style_NumberFormat::ToFormattedString( $cell->getValue(), - $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode() + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') ); } - - // Convert UTF8 data to PCDATA - $cellData = htmlspecialchars($cellData); } // replace leading spaces on each line with   @@ -910,19 +960,17 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $cellData = '' . $cellData . ''; } - // Column/rowspan - foreach ($pSheet->getMergeCells() as $cells) { - if ($cell->isInRange($cells)) { - list($first, ) = PHPExcel_Cell::splitRange($cells); + // Should the cell be written or is it swallowed by a rowspan or colspan? + $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]) + && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] ); - if ($first[0] == $cell->getCoordinate()) { - list($colSpan, $rowSpan) = PHPExcel_Cell::rangeDimension($cells); - } else { - $writeCell = false; - } - - break; - } + // Colspan and Rowspan + $colspan = 1; + $rowspan = 1; + if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) { + $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; + $rowSpan = $spans['rowspan']; + $colSpan = $spans['colspan']; } // Write @@ -1085,4 +1133,122 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $string; } + /** + * Add color to formatted string as inline style + * + * @param string $pValue Plain formatted value without color + * @param string $pFormat Format code + * @return string + */ + public function formatColor($pValue, $pFormat) + { + // Color information, e.g. [Red] is always at the beginning + $color = null; // initialize + $matches = array(); + + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + if (preg_match($color_regex, $pFormat, $matches)) { + $color = str_replace('[', '', $matches[0]); + $color = str_replace(']', '', $color); + $color = strtolower($color); + } + + // convert to PCDATA + $value = htmlspecialchars($pValue); + + // color span tag + if ($color !== null) { + $value = '' . $value . ''; + } + + return $value; + } + + /** + * Calculate information about HTML colspan and rowspan which is not always the same as Excel's + */ + private function _calculateSpans() + { + // Identify all cells that should be omitted in HTML due to cell merge. + // In HTML only the upper-left cell should be written and it should have + // appropriate rowspan / colspan attribute + $sheetIndexes = $this->_sheetIndex !== null ? + array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1); + + foreach ($sheetIndexes as $sheetIndex) { + $sheet = $this->_phpExcel->getSheet($sheetIndex); + + $candidateSpannedRow = array(); + + // loop through all Excel merged cells + foreach ($sheet->getMergeCells() as $cells) { + list($cells, ) = PHPExcel_Cell::splitRange($cells); + $first = $cells[0]; + $last = $cells[1]; + + list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first); + $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1; + + list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last); + $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1; + + // loop through the individual cells in the individual merge + for ($r = $fr; $r <= $lr; ++$r) { + // also, flag this row as a HTML row that is candidate to be omitted + $candidateSpannedRow[$r] = $r; + + for ($c = $fc; $c <= $lc; ++$c) { + if ( !($c == $fc && $r == $fr) ) { + // not the upper-left cell (should not be written in HTML) + $this->_isSpannedCell[$sheetIndex][$r][$c] = array( + 'baseCell' => array($fr, $fc), + ); + } else { + // upper-left is the base cell that should hold the colspan/rowspan attribute + $this->_isBaseCell[$sheetIndex][$r][$c] = array( + 'xlrowspan' => $lr - $fr + 1, // Excel rowspan + 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change + 'xlcolspan' => $lc - $fc + 1, // Excel colspan + 'colspan' => $lc - $fc + 1, // HTML colspan, value may change + ); + } + } + } + } + + // Identify which rows should be omitted in HTML. These are the rows where all the cells + // participate in a merge and the where base cells are somewhere above. + $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()); + foreach ($candidateSpannedRow as $rowIndex) { + if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) { + if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) { + $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; + }; + } + } + + // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1 + if ( isset($this->_isSpannedRow[$sheetIndex]) ) { + foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) { + $adjustedBaseCells = array(); + for ($c = 0; $c < $countColumns; ++$c) { + $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; + + if ( !in_array($baseCell, $adjustedBaseCells) ) { + + // subtract rowspan by 1 + --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan']; + $adjustedBaseCells[] = $baseCell; + } + } + } + } + + // TODO: Same for columns + } + + // We have calculated the spans + $this->_spansAreCalculated = true; + } + } diff --git a/libraries/PHPExcel/PHPExcel/Writer/IWriter.php b/libraries/PHPExcel/PHPExcel/Writer/IWriter.php index b8f0ba89f..063d755e7 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/IWriter.php +++ b/libraries/PHPExcel/PHPExcel/Writer/IWriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Writer_IWriter { diff --git a/libraries/PHPExcel/PHPExcel/Writer/PDF.php b/libraries/PHPExcel/PHPExcel/Writer/PDF.php index 6712c3929..cf2825d56 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/PDF.php +++ b/libraries/PHPExcel/PHPExcel/Writer/PDF.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -49,6 +49,9 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/RichText.php'; /** PHPExcel_Shared_Drawing */ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/Drawing.php'; +/** PHPExcel_Shared_File */ +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/File.php'; + /** PHPExcel_HashTable */ require_once PHPEXCEL_ROOT . 'PHPExcel/HashTable.php'; @@ -61,7 +64,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PDF.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_PDF extends PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { /** @@ -79,7 +82,7 @@ class PHPExcel_Writer_PDF extends PHPExcel_Writer_HTML implements PHPExcel_Write public function __construct(PHPExcel $phpExcel) { parent::__construct($phpExcel); $this->setUseInlineCss(true); - $this->_tempDir = sys_get_temp_dir(); + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); } /** @@ -129,7 +132,13 @@ class PHPExcel_Writer_PDF extends PHPExcel_Writer_HTML implements PHPExcel_Write $pdf->setPrintHeader(false); $pdf->setPrintFooter(false); $pdf->AddPage(); + + // Set the appropriate font $pdf->SetFont('freesans'); + //$pdf->SetFont('arialunicid0-chinese-simplified'); + //$pdf->SetFont('arialunicid0-chinese-traditional'); + //$pdf->SetFont('arialunicid0-korean'); + //$pdf->SetFont('arialunicid0-japanese'); $pdf->writeHTML($html); // Document info diff --git a/libraries/PHPExcel/PHPExcel/Writer/Serialized.php b/libraries/PHPExcel/PHPExcel/Writer/Serialized.php index 940a49969..d831b8eb1 100644 --- a/libraries/PHPExcel/PHPExcel/Writer/Serialized.php +++ b/libraries/PHPExcel/PHPExcel/Writer/Serialized.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2009 PHPExcel + * Copyright (c) 2006 - 2010 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.0, 2009-08-10 + * @version 1.7.2, 2010-01-11 */ @@ -58,7 +58,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/IWriter.php'; * * @category PHPExcel * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Serialized implements PHPExcel_Writer_IWriter { @@ -190,10 +190,10 @@ class PHPExcel_Writer_Serialized implements PHPExcel_Writer_IWriter // PHPExcel $objWriter->startElement('PHPExcel'); - $objWriter->writeAttribute('version', '1.7.0'); + $objWriter->writeAttribute('version', '1.7.2'); // Comment - $objWriter->writeComment('This file has been generated using PHPExcel v1.7.0 (http://www.codeplex.com/PHPExcel). It contains a base64 encoded serialized version of the PHPExcel internal object.'); + $objWriter->writeComment('This file has been generated using PHPExcel v1.7.2 (http://www.codeplex.com/PHPExcel). It contains a base64 encoded serialized version of the PHPExcel internal object.'); // Data $objWriter->startElement('data');