Browse Source

第二次推送项目3

master
wanghongjun 2 years ago
parent
commit
319b7edec7
  1. 289
      extend/PHPExcel/PHPExcel/Reader/Abstract.php
  2. 406
      extend/PHPExcel/PHPExcel/Reader/CSV.php
  3. 51
      extend/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php
  4. 801
      extend/PHPExcel/PHPExcel/Reader/Excel2003XML.php
  5. 2051
      extend/PHPExcel/PHPExcel/Reader/Excel2007.php
  6. 520
      extend/PHPExcel/PHPExcel/Reader/Excel2007/Chart.php
  7. 127
      extend/PHPExcel/PHPExcel/Reader/Excel2007/Theme.php
  8. 7594
      extend/PHPExcel/PHPExcel/Reader/Excel5.php
  9. 32
      extend/PHPExcel/PHPExcel/Reader/Excel5/Color.php
  10. 77
      extend/PHPExcel/PHPExcel/Reader/Excel5/Color/BIFF5.php
  11. 77
      extend/PHPExcel/PHPExcel/Reader/Excel5/Color/BIFF8.php
  12. 31
      extend/PHPExcel/PHPExcel/Reader/Excel5/Color/BuiltIn.php
  13. 28
      extend/PHPExcel/PHPExcel/Reader/Excel5/ErrorCode.php
  14. 669
      extend/PHPExcel/PHPExcel/Reader/Excel5/Escher.php
  15. 203
      extend/PHPExcel/PHPExcel/Reader/Excel5/MD5.php
  16. 81
      extend/PHPExcel/PHPExcel/Reader/Excel5/RC4.php
  17. 36
      extend/PHPExcel/PHPExcel/Reader/Excel5/Style/Border.php
  18. 41
      extend/PHPExcel/PHPExcel/Reader/Excel5/Style/FillPattern.php
  19. 46
      extend/PHPExcel/PHPExcel/Reader/Exception.php
  20. 850
      extend/PHPExcel/PHPExcel/Reader/Gnumeric.php
  21. 549
      extend/PHPExcel/PHPExcel/Reader/HTML.php
  22. 39
      extend/PHPExcel/PHPExcel/Reader/IReadFilter.php
  23. 46
      extend/PHPExcel/PHPExcel/Reader/IReader.php
  24. 696
      extend/PHPExcel/PHPExcel/Reader/OOCalc.php
  25. 478
      extend/PHPExcel/PHPExcel/Reader/SYLK.php
  26. 156
      extend/PHPExcel/PHPExcel/Shared/CodePage.php
  27. 418
      extend/PHPExcel/PHPExcel/Shared/Date.php
  28. 270
      extend/PHPExcel/PHPExcel/Shared/Drawing.php
  29. 83
      extend/PHPExcel/PHPExcel/Shared/Escher.php
  30. 75
      extend/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php
  31. 102
      extend/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php
  32. 388
      extend/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php
  33. 196
      extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php
  34. 57
      extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php
  35. 112
      extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php
  36. 83
      extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php
  37. 298
      extend/PHPExcel/PHPExcel/Shared/Excel5.php
  38. 180
      extend/PHPExcel/PHPExcel/Shared/File.php
  39. 741
      extend/PHPExcel/PHPExcel/Shared/Font.php
  40. 16
      extend/PHPExcel/PHPExcel/Shared/JAMA/CHANGELOG.TXT
  41. 148
      extend/PHPExcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php
  42. 864
      extend/PHPExcel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php
  43. 257
      extend/PHPExcel/PHPExcel/Shared/JAMA/LUDecomposition.php
  44. 1159
      extend/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php
  45. 235
      extend/PHPExcel/PHPExcel/Shared/JAMA/QRDecomposition.php
  46. 528
      extend/PHPExcel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php
  47. 83
      extend/PHPExcel/PHPExcel/Shared/JAMA/utils/Error.php
  48. 44
      extend/PHPExcel/PHPExcel/Shared/JAMA/utils/Maths.php
  49. 526
      extend/PHPExcel/PHPExcel/Shared/OLE.php
  50. 206
      extend/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php
  51. 230
      extend/PHPExcel/PHPExcel/Shared/OLE/PPS.php
  52. 74
      extend/PHPExcel/PHPExcel/Shared/OLE/PPS/File.php
  53. 462
      extend/PHPExcel/PHPExcel/Shared/OLE/PPS/Root.php
  54. 318
      extend/PHPExcel/PHPExcel/Shared/OLERead.php
  55. 504
      extend/PHPExcel/PHPExcel/Shared/PCLZip/gnu-lgpl.txt
  56. 5173
      extend/PHPExcel/PHPExcel/Shared/PCLZip/pclzip.lib.php
  57. 421
      extend/PHPExcel/PHPExcel/Shared/PCLZip/readme.txt
  58. 67
      extend/PHPExcel/PHPExcel/Shared/PasswordHasher.php
  59. 819
      extend/PHPExcel/PHPExcel/Shared/String.php
  60. 144
      extend/PHPExcel/PHPExcel/Shared/TimeZone.php
  61. 124
      extend/PHPExcel/PHPExcel/Shared/XMLWriter.php
  62. 163
      extend/PHPExcel/PHPExcel/Shared/ZipArchive.php
  63. 200
      extend/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php
  64. 425
      extend/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php
  65. 138
      extend/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php
  66. 102
      extend/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php
  67. 110
      extend/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php
  68. 222
      extend/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php
  69. 138
      extend/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php
  70. 147
      extend/PHPExcel/PHPExcel/Shared/trend/trendClass.php
  71. 846
      extend/PHPExcel/PHPExcel/Worksheet/AutoFilter.php
  72. 405
      extend/PHPExcel/PHPExcel/Worksheet/AutoFilter/Column.php
  73. 468
      extend/PHPExcel/PHPExcel/Worksheet/AutoFilter/Column/Rule.php
  74. 507
      extend/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php
  75. 88
      extend/PHPExcel/PHPExcel/Worksheet/CellIterator.php
  76. 86
      extend/PHPExcel/PHPExcel/Worksheet/Column.php
  77. 216
      extend/PHPExcel/PHPExcel/Worksheet/ColumnCellIterator.php
  78. 132
      extend/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php
  79. 201
      extend/PHPExcel/PHPExcel/Worksheet/ColumnIterator.php
  80. 178
      extend/PHPExcel/PHPExcel/Worksheet/Dimension.php
  81. 147
      extend/PHPExcel/PHPExcel/Worksheet/Drawing.php
  82. 296
      extend/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php
  83. 494
      extend/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php
  84. 361
      extend/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php
  85. 201
      extend/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php
  86. 233
      extend/PHPExcel/PHPExcel/Worksheet/PageMargins.php
  87. 839
      extend/PHPExcel/PHPExcel/Worksheet/PageSetup.php
  88. 581
      extend/PHPExcel/PHPExcel/Worksheet/Protection.php
  89. 86
      extend/PHPExcel/PHPExcel/Worksheet/Row.php
  90. 225
      extend/PHPExcel/PHPExcel/Worksheet/RowCellIterator.php
  91. 132
      extend/PHPExcel/PHPExcel/Worksheet/RowDimension.php
  92. 192
      extend/PHPExcel/PHPExcel/Worksheet/RowIterator.php
  93. 187
      extend/PHPExcel/PHPExcel/Worksheet/SheetView.php

289
extend/PHPExcel/PHPExcel/Reader/Abstract.php

@ -0,0 +1,289 @@
<?php
/**
* PHPExcel_Reader_Abstract
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
abstract class PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
{
/**
* Read data only?
* Identifies whether the Reader should only read data values for cells, and ignore any formatting information;
* or whether it should read both data and formatting
*
* @var boolean
*/
protected $readDataOnly = false;
/**
* Read empty cells?
* Identifies whether the Reader should read data values for cells all cells, or should ignore cells containing
* null value or empty string
*
* @var boolean
*/
protected $readEmptyCells = true;
/**
* Read charts that are defined in the workbook?
* Identifies whether the Reader should read the definitions for any charts that exist in the workbook;
*
* @var boolean
*/
protected $includeCharts = false;
/**
* Restrict which sheets should be loaded?
* This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded.
*
* @var array of string
*/
protected $loadSheetsOnly;
/**
* PHPExcel_Reader_IReadFilter instance
*
* @var PHPExcel_Reader_IReadFilter
*/
protected $readFilter;
protected $fileHandle = null;
/**
* Read data only?
* If this is true, then the Reader will only read data values for cells, it will not read any formatting information.
* If false (the default) it will read data and formatting.
*
* @return boolean
*/
public function getReadDataOnly()
{
return $this->readDataOnly;
}
/**
* Set read data only
* Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information.
* Set to false (the default) to advise the Reader to read both data and formatting for cells.
*
* @param boolean $pValue
*
* @return PHPExcel_Reader_IReader
*/
public function setReadDataOnly($pValue = false)
{
$this->readDataOnly = $pValue;
return $this;
}
/**
* Read empty cells?
* If this is true (the default), then the Reader will read data values for all cells, irrespective of value.
* If false it will not read data for cells containing a null value or an empty string.
*
* @return boolean
*/
public function getReadEmptyCells()
{
return $this->readEmptyCells;
}
/**
* Set read empty cells
* Set to true (the default) to advise the Reader read data values for all cells, irrespective of value.
* Set to false to advise the Reader to ignore cells containing a null value or an empty string.
*
* @param boolean $pValue
*
* @return PHPExcel_Reader_IReader
*/
public function setReadEmptyCells($pValue = true)
{
$this->readEmptyCells = $pValue;
return $this;
}
/**
* Read charts in workbook?
* If this is true, then the Reader will include any charts that exist in the workbook.
* Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value.
* If false (the default) it will ignore any charts defined in the workbook file.
*
* @return boolean
*/
public function getIncludeCharts()
{
return $this->includeCharts;
}
/**
* Set read charts in workbook
* Set to true, to advise the Reader to include any charts that exist in the workbook.
* Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value.
* Set to false (the default) to discard charts.
*
* @param boolean $pValue
*
* @return PHPExcel_Reader_IReader
*/
public function setIncludeCharts($pValue = false)
{
$this->includeCharts = (boolean) $pValue;
return $this;
}
/**
* Get which sheets to load
* Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null
* indicating that all worksheets in the workbook should be loaded.
*
* @return mixed
*/
public function getLoadSheetsOnly()
{
return $this->loadSheetsOnly;
}
/**
* Set which sheets to load
*
* @param mixed $value
* This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name.
* If NULL, then it tells the Reader to read all worksheets in the workbook
*
* @return PHPExcel_Reader_IReader
*/
public function setLoadSheetsOnly($value = null)
{
if ($value === null) {
return $this->setLoadAllSheets();
}
$this->loadSheetsOnly = is_array($value) ? $value : array($value);
return $this;
}
/**
* Set all sheets to load
* Tells the Reader to load all worksheets from the workbook.
*
* @return PHPExcel_Reader_IReader
*/
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_IReader
*/
public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue)
{
$this->readFilter = $pValue;
return $this;
}
/**
* Open file for reading
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
* @return resource
*/
protected function openFile($pFilename)
{
// Check if file exists
if (!file_exists($pFilename) || !is_readable($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
// Open file
$this->fileHandle = fopen($pFilename, 'r');
if ($this->fileHandle === false) {
throw new PHPExcel_Reader_Exception("Could not open file " . $pFilename . " for reading.");
}
}
/**
* Can the current PHPExcel_Reader_IReader read the file?
*
* @param string $pFilename
* @return boolean
* @throws PHPExcel_Reader_Exception
*/
public function canRead($pFilename)
{
// Check if file exists
try {
$this->openFile($pFilename);
} catch (Exception $e) {
return false;
}
$readable = $this->isValidFormat();
fclose($this->fileHandle);
return $readable;
}
/**
* Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks
*
* @param string $xml
* @throws PHPExcel_Reader_Exception
*/
public function securityScan($xml)
{
$pattern = '/\\0?' . implode('\\0?', str_split('<!DOCTYPE')) . '\\0?/';
if (preg_match($pattern, $xml)) {
throw new PHPExcel_Reader_Exception('Detected use of ENTITY in XML, spreadsheet file load() aborted to prevent XXE/XEE attacks');
}
return $xml;
}
/**
* Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks
*
* @param string $filestream
* @throws PHPExcel_Reader_Exception
*/
public function securityScanFile($filestream)
{
return $this->securityScan(file_get_contents($filestream));
}
}

406
extend/PHPExcel/PHPExcel/Reader/CSV.php

@ -0,0 +1,406 @@
<?php
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
/**
* @ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel_Reader_CSV
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_CSV extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
{
/**
* Input encoding
*
* @access private
* @var string
*/
private $inputEncoding = 'UTF-8';
/**
* Delimiter
*
* @access private
* @var string
*/
private $delimiter = ',';
/**
* Enclosure
*
* @access private
* @var string
*/
private $enclosure = '"';
/**
* Sheet index to read
*
* @access private
* @var int
*/
private $sheetIndex = 0;
/**
* Load rows contiguously
*
* @access private
* @var int
*/
private $contiguous = false;
/**
* Row counter for loading rows contiguously
*
* @var int
*/
private $contiguousRow = -1;
/**
* Create a new PHPExcel_Reader_CSV
*/
public function __construct()
{
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter();
}
/**
* Validate that the current file is a CSV file
*
* @return boolean
*/
protected function isValidFormat()
{
return true;
}
/**
* Set input encoding
*
* @param string $pValue Input encoding
*/
public function setInputEncoding($pValue = 'UTF-8')
{
$this->inputEncoding = $pValue;
return $this;
}
/**
* Get input encoding
*
* @return string
*/
public function getInputEncoding()
{
return $this->inputEncoding;
}
/**
* Move filepointer past any BOM marker
*
*/
protected function skipBOM()
{
rewind($this->fileHandle);
switch ($this->inputEncoding) {
case 'UTF-8':
fgets($this->fileHandle, 4) == "\xEF\xBB\xBF" ?
fseek($this->fileHandle, 3) : fseek($this->fileHandle, 0);
break;
case 'UTF-16LE':
fgets($this->fileHandle, 3) == "\xFF\xFE" ?
fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0);
break;
case 'UTF-16BE':
fgets($this->fileHandle, 3) == "\xFE\xFF" ?
fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0);
break;
case 'UTF-32LE':
fgets($this->fileHandle, 5) == "\xFF\xFE\x00\x00" ?
fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0);
break;
case 'UTF-32BE':
fgets($this->fileHandle, 5) == "\x00\x00\xFE\xFF" ?
fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0);
break;
default:
break;
}
}
/**
* Identify any separator that is explicitly set in the file
*
*/
protected function checkSeparator()
{
$line = fgets($this->fileHandle);
if ($line === false) {
return;
}
if ((strlen(trim($line, "\r\n")) == 5) && (stripos($line, 'sep=') === 0)) {
$this->delimiter = substr($line, 4, 1);
return;
}
return $this->skipBOM();
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetInfo($pFilename)
{
// Open file
$this->openFile($pFilename);
if (!$this->isValidFormat()) {
fclose($this->fileHandle);
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file.");
}
$fileHandle = $this->fileHandle;
// Skip BOM, if any
$this->skipBOM();
$this->checkSeparator();
$escapeEnclosures = array( "\\" . $this->enclosure, $this->enclosure . $this->enclosure );
$worksheetInfo = array();
$worksheetInfo[0]['worksheetName'] = 'Worksheet';
$worksheetInfo[0]['lastColumnLetter'] = 'A';
$worksheetInfo[0]['lastColumnIndex'] = 0;
$worksheetInfo[0]['totalRows'] = 0;
$worksheetInfo[0]['totalColumns'] = 0;
// Loop through each line of the file in turn
while (($rowData = fgetcsv($fileHandle, 0, $this->delimiter, $this->enclosure)) !== false) {
$worksheetInfo[0]['totalRows']++;
$worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], count($rowData) - 1);
}
$worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']);
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
// Close file
fclose($fileHandle);
return $worksheetInfo;
}
/**
* Loads PHPExcel from file
*
* @param string $pFilename
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function load($pFilename)
{
// Create new PHPExcel
$objPHPExcel = new PHPExcel();
// Load into this instance
return $this->loadIntoExisting($pFilename, $objPHPExcel);
}
/**
* Loads PHPExcel from file into PHPExcel instance
*
* @param string $pFilename
* @param PHPExcel $objPHPExcel
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
{
$lineEnding = ini_get('auto_detect_line_endings');
ini_set('auto_detect_line_endings', true);
// Open file
$this->openFile($pFilename);
if (!$this->isValidFormat()) {
fclose($this->fileHandle);
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file.");
}
$fileHandle = $this->fileHandle;
// Skip BOM, if any
$this->skipBOM();
$this->checkSeparator();
// Create new PHPExcel object
while ($objPHPExcel->getSheetCount() <= $this->sheetIndex) {
$objPHPExcel->createSheet();
}
$sheet = $objPHPExcel->setActiveSheetIndex($this->sheetIndex);
$escapeEnclosures = array( "\\" . $this->enclosure,
$this->enclosure . $this->enclosure
);
// Set our starting row based on whether we're in contiguous mode or not
$currentRow = 1;
if ($this->contiguous) {
$currentRow = ($this->contiguousRow == -1) ? $sheet->getHighestRow(): $this->contiguousRow;
}
// Loop through each line of the file in turn
while (($rowData = fgetcsv($fileHandle, 0, $this->delimiter, $this->enclosure)) !== false) {
$columnLetter = 'A';
foreach ($rowData as $rowDatum) {
if ($rowDatum != '' && $this->readFilter->readCell($columnLetter, $currentRow)) {
// Unescape enclosures
$rowDatum = str_replace($escapeEnclosures, $this->enclosure, $rowDatum);
// Convert encoding if necessary
if ($this->inputEncoding !== 'UTF-8') {
$rowDatum = PHPExcel_Shared_String::ConvertEncoding($rowDatum, 'UTF-8', $this->inputEncoding);
}
// Set cell value
$sheet->getCell($columnLetter . $currentRow)->setValue($rowDatum);
}
++$columnLetter;
}
++$currentRow;
}
// Close file
fclose($fileHandle);
if ($this->contiguous) {
$this->contiguousRow = $currentRow;
}
ini_set('auto_detect_line_endings', $lineEnding);
// Return
return $objPHPExcel;
}
/**
* Get delimiter
*
* @return string
*/
public function getDelimiter()
{
return $this->delimiter;
}
/**
* Set delimiter
*
* @param string $pValue Delimiter, defaults to ,
* @return PHPExcel_Reader_CSV
*/
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_CSV
*/
public function setEnclosure($pValue = '"')
{
if ($pValue == '') {
$pValue = '"';
}
$this->enclosure = $pValue;
return $this;
}
/**
* Get sheet index
*
* @return integer
*/
public function getSheetIndex()
{
return $this->sheetIndex;
}
/**
* Set sheet index
*
* @param integer $pValue Sheet index
* @return PHPExcel_Reader_CSV
*/
public function setSheetIndex($pValue = 0)
{
$this->sheetIndex = $pValue;
return $this;
}
/**
* Set Contiguous
*
* @param boolean $contiguous
*/
public function setContiguous($contiguous = false)
{
$this->contiguous = (bool) $contiguous;
if (!$contiguous) {
$this->contiguousRow = -1;
}
return $this;
}
/**
* Get Contiguous
*
* @return boolean
*/
public function getContiguous()
{
return $this->contiguous;
}
}

51
extend/PHPExcel/PHPExcel/Reader/DefaultReadFilter.php

@ -0,0 +1,51 @@
<?php
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
/**
* @ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel_Reader_DefaultReadFilter
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter
{
/**
* Should this cell be read?
*
* @param $column Column address (as a string value like "A", or "IV")
* @param $row Row number
* @param $worksheetName Optional worksheet name
* @return boolean
*/
public function readCell($column, $row, $worksheetName = '')
{
return true;
}
}

801
extend/PHPExcel/PHPExcel/Reader/Excel2003XML.php

@ -0,0 +1,801 @@
<?php
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
/**
* @ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel_Reader_Excel2003XML
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_Excel2003XML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
{
/**
* Formats
*
* @var array
*/
protected $styles = array();
/**
* Character set used in the file
*
* @var string
*/
protected $charSet = 'UTF-8';
/**
* Create a new PHPExcel_Reader_Excel2003XML
*/
public function __construct()
{
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter();
}
/**
* Can the current PHPExcel_Reader_IReader read the file?
*
* @param string $pFilename
* @return boolean
* @throws PHPExcel_Reader_Exception
*/
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(
'<?xml version="1.0"',
'<?mso-application progid="Excel.Sheet"?>'
);
// Open file
$this->openFile($pFilename);
$fileHandle = $this->fileHandle;
// Read sample data (first 2 KB will do)
$data = fread($fileHandle, 2048);
fclose($fileHandle);
$valid = true;
foreach ($signature as $match) {
// every part of the signature must be present
if (strpos($data, $match) === false) {
$valid = false;
break;
}
}
// Retrieve charset encoding
if (preg_match('/<?xml.*encoding=[\'"](.*?)[\'"].*?>/um', $data, $matches)) {
$this->charSet = strtoupper($matches[1]);
}
// echo 'Character Set is ', $this->charSet,'<br />';
return $valid;
}
/**
* Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetNames($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
if (!$this->canRead($pFilename)) {
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file.");
}
$worksheetNames = array();
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
$namespaces = $xml->getNamespaces(true);
$xml_ss = $xml->children($namespaces['ss']);
foreach ($xml_ss->Worksheet as $worksheet) {
$worksheet_ss = $worksheet->attributes($namespaces['ss']);
$worksheetNames[] = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet);
}
return $worksheetNames;
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetInfo($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$worksheetInfo = array();
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
$namespaces = $xml->getNamespaces(true);
$worksheetID = 1;
$xml_ss = $xml->children($namespaces['ss']);
foreach ($xml_ss->Worksheet as $worksheet) {
$worksheet_ss = $worksheet->attributes($namespaces['ss']);
$tmpInfo = array();
$tmpInfo['worksheetName'] = '';
$tmpInfo['lastColumnLetter'] = 'A';
$tmpInfo['lastColumnIndex'] = 0;
$tmpInfo['totalRows'] = 0;
$tmpInfo['totalColumns'] = 0;
if (isset($worksheet_ss['Name'])) {
$tmpInfo['worksheetName'] = (string) $worksheet_ss['Name'];
} else {
$tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}";
}
if (isset($worksheet->Table->Row)) {
$rowIndex = 0;
foreach ($worksheet->Table->Row as $rowData) {
$columnIndex = 0;
$rowHasData = false;
foreach ($rowData->Cell as $cell) {
if (isset($cell->Data)) {
$tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex);
$rowHasData = true;
}
++$columnIndex;
}
++$rowIndex;
if ($rowHasData) {
$tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex);
}
}
}
$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
$tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1;
$worksheetInfo[] = $tmpInfo;
++$worksheetID;
}
return $worksheetInfo;
}
/**
* Loads PHPExcel from file
*
* @param string $pFilename
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function load($pFilename)
{
// Create new PHPExcel
$objPHPExcel = new PHPExcel();
$objPHPExcel->removeSheetByIndex(0);
// Load into this instance
return $this->loadIntoExisting($pFilename, $objPHPExcel);
}
protected 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
*/
protected 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
*/
protected static function widthUnits2Pixel($widthUnits)
{
$pixels = ($widthUnits / 256) * 7;
$offsetWidthUnits = $widthUnits % 256;
$pixels += round($offsetWidthUnits / (256 / 7));
return $pixels;
}
protected static function hex2str($hex)
{
return chr(hexdec($hex[1]));
}
/**
* Loads PHPExcel from file into PHPExcel instance
*
* @param string $pFilename
* @param PHPExcel $objPHPExcel
* @return PHPExcel
* @throws PHPExcel_Reader_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
);
$timezoneObj = new DateTimeZone('Europe/London');
$GMT = new DateTimeZone('UTC');
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
if (!$this->canRead($pFilename)) {
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file.");
}
$xml = simplexml_load_string($this->securityScan(file_get_contents($pFilename)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
$namespaces = $xml->getNamespaces(true);
$docProps = $objPHPExcel->getProperties();
if (isset($xml->DocumentProperties[0])) {
foreach ($xml->DocumentProperties[0] as $propertyName => $propertyValue) {
switch ($propertyName) {
case 'Title':
$docProps->setTitle(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'Subject':
$docProps->setSubject(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'Author':
$docProps->setCreator(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'Created':
$creationDate = strtotime($propertyValue);
$docProps->setCreated($creationDate);
break;
case 'LastAuthor':
$docProps->setLastModifiedBy(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'LastSaved':
$lastSaveDate = strtotime($propertyValue);
$docProps->setModified($lastSaveDate);
break;
case 'Company':
$docProps->setCompany(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'Category':
$docProps->setCategory(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'Manager':
$docProps->setManager(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'Keywords':
$docProps->setKeywords(self::convertStringEncoding($propertyValue, $this->charSet));
break;
case 'Description':
$docProps->setDescription(self::convertStringEncoding($propertyValue, $this->charSet));
break;
}
}
}
if (isset($xml->CustomDocumentProperties)) {
foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) {
$propertyAttributes = $propertyValue->attributes($namespaces['dt']);
$propertyName = preg_replace_callback('/_x([0-9a-z]{4})_/', 'PHPExcel_Reader_Excel2003XML::hex2str', $propertyName);
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_UNKNOWN;
switch ((string) $propertyAttributes) {
case 'string':
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING;
$propertyValue = trim($propertyValue);
break;
case 'boolean':
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN;
$propertyValue = (bool) $propertyValue;
break;
case 'integer':
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_INTEGER;
$propertyValue = intval($propertyValue);
break;
case 'float':
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT;
$propertyValue = floatval($propertyValue);
break;
case 'dateTime.tz':
$propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE;
$propertyValue = strtotime(trim($propertyValue));
break;
}
$docProps->setCustomProperty($propertyName, $propertyValue, $propertyType);
}
}
foreach ($xml->Styles[0] as $style) {
$style_ss = $style->attributes($namespaces['ss']);
$styleID = (string) $style_ss['ID'];
// echo 'Style ID = '.$styleID.'<br />';
$this->styles[$styleID] = (isset($this->styles['Default'])) ? $this->styles['Default'] : array();
foreach ($style as $styleType => $styleData) {
$styleAttributes = $styleData->attributes($namespaces['ss']);
// echo $styleType.'<br />';
switch ($styleType) {
case 'Alignment':
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<br />';
$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.'<br />';
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 (!empty($thisBorder)) {
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.'<br />';
$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.'<br />';
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.'<br />';
$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.'<br />';
}
break;
}
}
// print_r($this->styles[$styleID]);
// echo '<hr />';
}
// echo '<hr />';
$worksheetID = 0;
$xml_ss = $xml->children($namespaces['ss']);
foreach ($xml_ss->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;
}
// echo '<h3>Worksheet: ', $worksheet_ss['Name'],'<h3>';
//
// Create new Worksheet
$objPHPExcel->createSheet();
$objPHPExcel->setActiveSheetIndex($worksheetID);
if (isset($worksheet_ss['Name'])) {
$worksheetName = self::convertStringEncoding((string) $worksheet_ss['Name'], $this->charSet);
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in
// formula cells... during the load, all formulae should be correct, and we're simply bringing
// the worksheet name in line with the formula, not the reverse
$objPHPExcel->getActiveSheet()->setTitle($worksheetName, false);
}
$columnID = 'A';
if (isset($worksheet->Table->Column)) {
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 '<b>Setting column width for '.$columnID.' to '.$columnWidth.'</b><br />';
$objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4);
}
++$columnID;
}
}
$rowID = 1;
if (isset($worksheet->Table->Row)) {
$additionalMergedCells = 0;
foreach ($worksheet->Table->Row as $rowData) {
$rowHasData = false;
$row_ss = $rowData->attributes($namespaces['ss']);
if (isset($row_ss['Index'])) {
$rowID = (integer) $row_ss['Index'];
}
// echo '<b>Row '.$rowID.'</b><br />';
$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 ($this->getReadFilter() !== null) {
if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) {
continue;
}
}
if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) {
$columnTo = $columnID;
if (isset($cell_ss['MergeAcross'])) {
$additionalMergedCells += (int)$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);
}
$cellIsSet = $hasCalculatedValue = false;
$cellDataFormula = '';
if (isset($cell_ss['Formula'])) {
$cellDataFormula = $cell_ss['Formula'];
// added this as a check for array formulas
if (isset($cell_ss['ArrayRange'])) {
$cellDataCSEFormula = $cell_ss['ArrayRange'];
// echo "found an array formula at ".$columnID.$rowID."<br />";
}
$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 = 'null';
const TYPE_INLINE = 'inlineStr';
const TYPE_ERROR = 'e';
*/
case 'String':
$cellValue = self::convertStringEncoding($cellValue, $this->charSet);
$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) {
// echo 'FORMULA<br />';
$type = PHPExcel_Cell_DataType::TYPE_FORMULA;
$columnNumber = PHPExcel_Cell::columnIndexFromString($columnID);
if (substr($cellDataFormula, 0, 3) == 'of:') {
$cellDataFormula = substr($cellDataFormula, 3);
// echo 'Before: ', $cellDataFormula,'<br />';
$temp = explode('"', $cellDataFormula);
$key = false;
foreach ($temp as &$value) {
// Only replace in alternate array entries (i.e. non-quoted blocks)
if ($key = !$key) {
$value = str_replace(array('[.', '.', ']'), '', $value);
}
}
} else {
// Convert R1C1 style references to A1 style references (but only when not quoted)
// echo 'Before: ', $cellDataFormula,'<br />';
$temp = explode('"', $cellDataFormula);
$key = false;
foreach ($temp as &$value) {
// Only replace in alternate array entries (i.e. non-quoted blocks)
if ($key = !$key) {
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 'After: ', $cellDataFormula,'<br />';
}
// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'<br />';
//
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue), $type);
if ($hasCalculatedValue) {
// echo 'Formula result is '.$cellValue.'<br />';
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue);
}
$cellIsSet = $rowHasData = true;
}
if (isset($cell->Comment)) {
// echo '<b>comment found</b><br />';
$commentAttributes = $cell->Comment->attributes($namespaces['ss']);
$author = 'unknown';
if (isset($commentAttributes->Author)) {
$author = (string)$commentAttributes->Author;
// echo 'Author: ', $author,'<br />';
}
$node = $cell->Comment->Data->asXML();
// $annotation = str_replace('html:','',substr($node,49,-10));
// echo $annotation,'<br />';
$annotation = strip_tags($node);
// echo 'Annotation: ', $annotation,'<br />';
$objPHPExcel->getActiveSheet()->getComment($columnID.$rowID)->setAuthor(self::convertStringEncoding($author, $this->charSet))->setText($this->parseRichText($annotation));
}
if (($cellIsSet) && (isset($cell_ss['StyleID']))) {
$style = (string) $cell_ss['StyleID'];
// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'<br />';
if ((isset($this->styles[$style])) && (!empty($this->styles[$style]))) {
// echo 'Cell '.$columnID.$rowID.'<br />';
// print_r($this->styles[$style]);
// echo '<br />';
if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) {
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValue(null);
}
$objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->styles[$style]);
}
}
++$columnID;
while ($additionalMergedCells > 0) {
++$columnID;
$additionalMergedCells--;
}
}
if ($rowHasData) {
if (isset($row_ss['StyleID'])) {
$rowStyle = $row_ss['StyleID'];
}
if (isset($row_ss['Height'])) {
$rowHeight = $row_ss['Height'];
// echo '<b>Setting row height to '.$rowHeight.'</b><br />';
$objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight);
}
}
++$rowID;
}
}
++$worksheetID;
}
// Return
return $objPHPExcel;
}
protected static function convertStringEncoding($string, $charset)
{
if ($charset != 'UTF-8') {
return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', $charset);
}
return $string;
}
protected function parseRichText($is = '')
{
$value = new PHPExcel_RichText();
$value->createText(self::convertStringEncoding($is, $this->charSet));
return $value;
}
}

2051
extend/PHPExcel/PHPExcel/Reader/Excel2007.php

File diff suppressed because it is too large

520
extend/PHPExcel/PHPExcel/Reader/Excel2007/Chart.php

@ -0,0 +1,520 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Reader_Excel2007
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Reader_Excel2007_Chart
*
* @category PHPExcel
* @package PHPExcel_Reader_Excel2007
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Reader_Excel2007_Chart
{
private static function getAttribute($component, $name, $format)
{
$attributes = $component->attributes();
if (isset($attributes[$name])) {
if ($format == 'string') {
return (string) $attributes[$name];
} elseif ($format == 'integer') {
return (integer) $attributes[$name];
} elseif ($format == 'boolean') {
return (boolean) ($attributes[$name] === '0' || $attributes[$name] !== 'true') ? false : true;
} else {
return (float) $attributes[$name];
}
}
return null;
}
private static function readColor($color, $background = false)
{
if (isset($color["rgb"])) {
return (string)$color["rgb"];
} elseif (isset($color["indexed"])) {
return PHPExcel_Style_Color::indexedColor($color["indexed"]-7, $background)->getARGB();
}
}
public static function readChart($chartElements, $chartName)
{
$namespacesChartMeta = $chartElements->getNamespaces(true);
$chartElementsC = $chartElements->children($namespacesChartMeta['c']);
$XaxisLabel = $YaxisLabel = $legend = $title = null;
$dispBlanksAs = $plotVisOnly = null;
foreach ($chartElementsC as $chartElementKey => $chartElement) {
switch ($chartElementKey) {
case "chart":
foreach ($chartElement as $chartDetailsKey => $chartDetails) {
$chartDetailsC = $chartDetails->children($namespacesChartMeta['c']);
switch ($chartDetailsKey) {
case "plotArea":
$plotAreaLayout = $XaxisLable = $YaxisLable = null;
$plotSeries = $plotAttributes = array();
foreach ($chartDetails as $chartDetailKey => $chartDetail) {
switch ($chartDetailKey) {
case "layout":
$plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta, 'plotArea');
break;
case "catAx":
if (isset($chartDetail->title)) {
$XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta, 'cat');
}
break;
case "dateAx":
if (isset($chartDetail->title)) {
$XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta, 'cat');
}
break;
case "valAx":
if (isset($chartDetail->title)) {
$YaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta, 'cat');
}
break;
case "barChart":
case "bar3DChart":
$barDirection = self::getAttribute($chartDetail->barDir, 'val', 'string');
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotSer->setPlotDirection($barDirection);
$plotSeries[] = $plotSer;
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "lineChart":
case "line3DChart":
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "areaChart":
case "area3DChart":
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "doughnutChart":
case "pieChart":
case "pie3DChart":
$explosion = isset($chartDetail->ser->explosion);
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotSer->setPlotStyle($explosion);
$plotSeries[] = $plotSer;
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "scatterChart":
$scatterStyle = self::getAttribute($chartDetail->scatterStyle, 'val', 'string');
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotSer->setPlotStyle($scatterStyle);
$plotSeries[] = $plotSer;
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "bubbleChart":
$bubbleScale = self::getAttribute($chartDetail->bubbleScale, 'val', 'integer');
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotSer->setPlotStyle($bubbleScale);
$plotSeries[] = $plotSer;
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "radarChart":
$radarStyle = self::getAttribute($chartDetail->radarStyle, 'val', 'string');
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotSer->setPlotStyle($radarStyle);
$plotSeries[] = $plotSer;
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "surfaceChart":
case "surface3DChart":
$wireFrame = self::getAttribute($chartDetail->wireframe, 'val', 'boolean');
$plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotSer->setPlotStyle($wireFrame);
$plotSeries[] = $plotSer;
$plotAttributes = self::readChartAttributes($chartDetail);
break;
case "stockChart":
$plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
$plotAttributes = self::readChartAttributes($plotAreaLayout);
break;
}
}
if ($plotAreaLayout == null) {
$plotAreaLayout = new PHPExcel_Chart_Layout();
}
$plotArea = new PHPExcel_Chart_PlotArea($plotAreaLayout, $plotSeries);
self::setChartAttributes($plotAreaLayout, $plotAttributes);
break;
case "plotVisOnly":
$plotVisOnly = self::getAttribute($chartDetails, 'val', 'string');
break;
case "dispBlanksAs":
$dispBlanksAs = self::getAttribute($chartDetails, 'val', 'string');
break;
case "title":
$title = self::chartTitle($chartDetails, $namespacesChartMeta, 'title');
break;
case "legend":
$legendPos = 'r';
$legendLayout = null;
$legendOverlay = false;
foreach ($chartDetails as $chartDetailKey => $chartDetail) {
switch ($chartDetailKey) {
case "legendPos":
$legendPos = self::getAttribute($chartDetail, 'val', 'string');
break;
case "overlay":
$legendOverlay = self::getAttribute($chartDetail, 'val', 'boolean');
break;
case "layout":
$legendLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta, 'legend');
break;
}
}
$legend = new PHPExcel_Chart_Legend($legendPos, $legendLayout, $legendOverlay);
break;
}
}
}
}
$chart = new PHPExcel_Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, $dispBlanksAs, $XaxisLabel, $YaxisLabel);
return $chart;
}
private static function chartTitle($titleDetails, $namespacesChartMeta, $type)
{
$caption = array();
$titleLayout = null;
foreach ($titleDetails as $titleDetailKey => $chartDetail) {
switch ($titleDetailKey) {
case "tx":
$titleDetails = $chartDetail->rich->children($namespacesChartMeta['a']);
foreach ($titleDetails as $titleKey => $titleDetail) {
switch ($titleKey) {
case "p":
$titleDetailPart = $titleDetail->children($namespacesChartMeta['a']);
$caption[] = self::parseRichText($titleDetailPart);
}
}
break;
case "layout":
$titleLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);
break;
}
}
return new PHPExcel_Chart_Title($caption, $titleLayout);
}
private static function chartLayoutDetails($chartDetail, $namespacesChartMeta)
{
if (!isset($chartDetail->manualLayout)) {
return null;
}
$details = $chartDetail->manualLayout->children($namespacesChartMeta['c']);
if (is_null($details)) {
return null;
}
$layout = array();
foreach ($details as $detailKey => $detail) {
// echo $detailKey, ' => ',self::getAttribute($detail, 'val', 'string'),PHP_EOL;
$layout[$detailKey] = self::getAttribute($detail, 'val', 'string');
}
return new PHPExcel_Chart_Layout($layout);
}
private static function chartDataSeries($chartDetail, $namespacesChartMeta, $plotType)
{
$multiSeriesType = null;
$smoothLine = false;
$seriesLabel = $seriesCategory = $seriesValues = $plotOrder = array();
$seriesDetailSet = $chartDetail->children($namespacesChartMeta['c']);
foreach ($seriesDetailSet as $seriesDetailKey => $seriesDetails) {
switch ($seriesDetailKey) {
case "grouping":
$multiSeriesType = self::getAttribute($chartDetail->grouping, 'val', 'string');
break;
case "ser":
$marker = null;
foreach ($seriesDetails as $seriesKey => $seriesDetail) {
switch ($seriesKey) {
case "idx":
$seriesIndex = self::getAttribute($seriesDetail, 'val', 'integer');
break;
case "order":
$seriesOrder = self::getAttribute($seriesDetail, 'val', 'integer');
$plotOrder[$seriesIndex] = $seriesOrder;
break;
case "tx":
$seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
break;
case "marker":
$marker = self::getAttribute($seriesDetail->symbol, 'val', 'string');
break;
case "smooth":
$smoothLine = self::getAttribute($seriesDetail, 'val', 'boolean');
break;
case "cat":
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
break;
case "val":
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
break;
case "xVal":
$seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
break;
case "yVal":
$seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
break;
}
}
}
}
return new PHPExcel_Chart_DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine);
}
private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null, $smoothLine = false)
{
if (isset($seriesDetail->strRef)) {
$seriesSource = (string) $seriesDetail->strRef->f;
$seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's');
return new PHPExcel_Chart_DataSeriesValues('String', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine);
} elseif (isset($seriesDetail->numRef)) {
$seriesSource = (string) $seriesDetail->numRef->f;
$seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c']));
return new PHPExcel_Chart_DataSeriesValues('Number', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine);
} elseif (isset($seriesDetail->multiLvlStrRef)) {
$seriesSource = (string) $seriesDetail->multiLvlStrRef->f;
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's');
$seriesData['pointCount'] = count($seriesData['dataValues']);
return new PHPExcel_Chart_DataSeriesValues('String', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine);
} elseif (isset($seriesDetail->multiLvlNumRef)) {
$seriesSource = (string) $seriesDetail->multiLvlNumRef->f;
$seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's');
$seriesData['pointCount'] = count($seriesData['dataValues']);
return new PHPExcel_Chart_DataSeriesValues('String', $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker, $smoothLine);
}
return null;
}
private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n')
{
$seriesVal = array();
$formatCode = '';
$pointCount = 0;
foreach ($seriesValueSet as $seriesValueIdx => $seriesValue) {
switch ($seriesValueIdx) {
case 'ptCount':
$pointCount = self::getAttribute($seriesValue, 'val', 'integer');
break;
case 'formatCode':
$formatCode = (string) $seriesValue;
break;
case 'pt':
$pointVal = self::getAttribute($seriesValue, 'idx', 'integer');
if ($dataType == 's') {
$seriesVal[$pointVal] = (string) $seriesValue->v;
} else {
$seriesVal[$pointVal] = (float) $seriesValue->v;
}
break;
}
}
return array(
'formatCode' => $formatCode,
'pointCount' => $pointCount,
'dataValues' => $seriesVal
);
}
private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n')
{
$seriesVal = array();
$formatCode = '';
$pointCount = 0;
foreach ($seriesValueSet->lvl as $seriesLevelIdx => $seriesLevel) {
foreach ($seriesLevel as $seriesValueIdx => $seriesValue) {
switch ($seriesValueIdx) {
case 'ptCount':
$pointCount = self::getAttribute($seriesValue, 'val', 'integer');
break;
case 'formatCode':
$formatCode = (string) $seriesValue;
break;
case 'pt':
$pointVal = self::getAttribute($seriesValue, 'idx', 'integer');
if ($dataType == 's') {
$seriesVal[$pointVal][] = (string) $seriesValue->v;
} else {
$seriesVal[$pointVal][] = (float) $seriesValue->v;
}
break;
}
}
}
return array(
'formatCode' => $formatCode,
'pointCount' => $pointCount,
'dataValues' => $seriesVal
);
}
private static function parseRichText($titleDetailPart = null)
{
$value = new PHPExcel_RichText();
foreach ($titleDetailPart as $titleDetailElementKey => $titleDetailElement) {
if (isset($titleDetailElement->t)) {
$objText = $value->createTextRun((string) $titleDetailElement->t);
}
if (isset($titleDetailElement->rPr)) {
if (isset($titleDetailElement->rPr->rFont["val"])) {
$objText->getFont()->setName((string) $titleDetailElement->rPr->rFont["val"]);
}
$fontSize = (self::getAttribute($titleDetailElement->rPr, 'sz', 'integer'));
if (!is_null($fontSize)) {
$objText->getFont()->setSize(floor($fontSize / 100));
}
$fontColor = (self::getAttribute($titleDetailElement->rPr, 'color', 'string'));
if (!is_null($fontColor)) {
$objText->getFont()->setColor(new PHPExcel_Style_Color(self::readColor($fontColor)));
}
$bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean');
if (!is_null($bold)) {
$objText->getFont()->setBold($bold);
}
$italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean');
if (!is_null($italic)) {
$objText->getFont()->setItalic($italic);
}
$baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer');
if (!is_null($baseline)) {
if ($baseline > 0) {
$objText->getFont()->setSuperScript(true);
} elseif ($baseline < 0) {
$objText->getFont()->setSubScript(true);
}
}
$underscore = (self::getAttribute($titleDetailElement->rPr, 'u', 'string'));
if (!is_null($underscore)) {
if ($underscore == 'sng') {
$objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE);
} elseif ($underscore == 'dbl') {
$objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLE);
} else {
$objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_NONE);
}
}
$strikethrough = (self::getAttribute($titleDetailElement->rPr, 's', 'string'));
if (!is_null($strikethrough)) {
if ($strikethrough == 'noStrike') {
$objText->getFont()->setStrikethrough(false);
} else {
$objText->getFont()->setStrikethrough(true);
}
}
}
}
return $value;
}
private static function readChartAttributes($chartDetail)
{
$plotAttributes = array();
if (isset($chartDetail->dLbls)) {
if (isset($chartDetail->dLbls->howLegendKey)) {
$plotAttributes['showLegendKey'] = self::getAttribute($chartDetail->dLbls->showLegendKey, 'val', 'string');
}
if (isset($chartDetail->dLbls->showVal)) {
$plotAttributes['showVal'] = self::getAttribute($chartDetail->dLbls->showVal, 'val', 'string');
}
if (isset($chartDetail->dLbls->showCatName)) {
$plotAttributes['showCatName'] = self::getAttribute($chartDetail->dLbls->showCatName, 'val', 'string');
}
if (isset($chartDetail->dLbls->showSerName)) {
$plotAttributes['showSerName'] = self::getAttribute($chartDetail->dLbls->showSerName, 'val', 'string');
}
if (isset($chartDetail->dLbls->showPercent)) {
$plotAttributes['showPercent'] = self::getAttribute($chartDetail->dLbls->showPercent, 'val', 'string');
}
if (isset($chartDetail->dLbls->showBubbleSize)) {
$plotAttributes['showBubbleSize'] = self::getAttribute($chartDetail->dLbls->showBubbleSize, 'val', 'string');
}
if (isset($chartDetail->dLbls->showLeaderLines)) {
$plotAttributes['showLeaderLines'] = self::getAttribute($chartDetail->dLbls->showLeaderLines, 'val', 'string');
}
}
return $plotAttributes;
}
private static function setChartAttributes($plotArea, $plotAttributes)
{
foreach ($plotAttributes as $plotAttributeKey => $plotAttributeValue) {
switch ($plotAttributeKey) {
case 'showLegendKey':
$plotArea->setShowLegendKey($plotAttributeValue);
break;
case 'showVal':
$plotArea->setShowVal($plotAttributeValue);
break;
case 'showCatName':
$plotArea->setShowCatName($plotAttributeValue);
break;
case 'showSerName':
$plotArea->setShowSerName($plotAttributeValue);
break;
case 'showPercent':
$plotArea->setShowPercent($plotAttributeValue);
break;
case 'showBubbleSize':
$plotArea->setShowBubbleSize($plotAttributeValue);
break;
case 'showLeaderLines':
$plotArea->setShowLeaderLines($plotAttributeValue);
break;
}
}
}
}

127
extend/PHPExcel/PHPExcel/Reader/Excel2007/Theme.php

@ -0,0 +1,127 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Reader_Excel2007
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Reader_Excel2007_Theme
*
* @category PHPExcel
* @package PHPExcel_Reader_Excel2007
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Reader_Excel2007_Theme
{
/**
* Theme Name
*
* @var string
*/
private $themeName;
/**
* Colour Scheme Name
*
* @var string
*/
private $colourSchemeName;
/**
* Colour Map indexed by position
*
* @var array of string
*/
private $colourMapValues;
/**
* Colour Map
*
* @var array of string
*/
private $colourMap;
/**
* Create a new PHPExcel_Theme
*
*/
public function __construct($themeName, $colourSchemeName, $colourMap)
{
// Initialise values
$this->themeName = $themeName;
$this->colourSchemeName = $colourSchemeName;
$this->colourMap = $colourMap;
}
/**
* Get Theme Name
*
* @return string
*/
public function getThemeName()
{
return $this->themeName;
}
/**
* Get colour Scheme Name
*
* @return string
*/
public function getColourSchemeName()
{
return $this->colourSchemeName;
}
/**
* Get colour Map Value by Position
*
* @return string
*/
public function getColourByIndex($index = 0)
{
if (isset($this->colourMap[$index])) {
return $this->colourMap[$index];
}
return null;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if ((is_object($value)) && ($key != '_parent')) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

7594
extend/PHPExcel/PHPExcel/Reader/Excel5.php

File diff suppressed because it is too large

32
extend/PHPExcel/PHPExcel/Reader/Excel5/Color.php

@ -0,0 +1,32 @@
<?php
class PHPExcel_Reader_Excel5_Color
{
/**
* Read color
*
* @param int $color Indexed color
* @param array $palette Color palette
* @return array RGB color value, example: array('rgb' => 'FF0000')
*/
public static function map($color, $palette, $version)
{
if ($color <= 0x07 || $color >= 0x40) {
// special built-in color
return PHPExcel_Reader_Excel5_Color_BuiltIn::lookup($color);
} elseif (isset($palette) && isset($palette[$color - 8])) {
// palette color, color index 0x08 maps to pallete index 0
return $palette[$color - 8];
} else {
// default color table
if ($version == PHPExcel_Reader_Excel5::XLS_BIFF8) {
return PHPExcel_Reader_Excel5_Color_BIFF8::lookup($color);
} else {
// BIFF5
return PHPExcel_Reader_Excel5_Color_BIFF5::lookup($color);
}
}
return $color;
}
}

77
extend/PHPExcel/PHPExcel/Reader/Excel5/Color/BIFF5.php

@ -0,0 +1,77 @@
<?php
class PHPExcel_Reader_Excel5_Color_BIFF5
{
protected static $map = array(
0x08 => '000000',
0x09 => 'FFFFFF',
0x0A => 'FF0000',
0x0B => '00FF00',
0x0C => '0000FF',
0x0D => 'FFFF00',
0x0E => 'FF00FF',
0x0F => '00FFFF',
0x10 => '800000',
0x11 => '008000',
0x12 => '000080',
0x13 => '808000',
0x14 => '800080',
0x15 => '008080',
0x16 => 'C0C0C0',
0x17 => '808080',
0x18 => '8080FF',
0x19 => '802060',
0x1A => 'FFFFC0',
0x1B => 'A0E0F0',
0x1C => '600080',
0x1D => 'FF8080',
0x1E => '0080C0',
0x1F => 'C0C0FF',
0x20 => '000080',
0x21 => 'FF00FF',
0x22 => 'FFFF00',
0x23 => '00FFFF',
0x24 => '800080',
0x25 => '800000',
0x26 => '008080',
0x27 => '0000FF',
0x28 => '00CFFF',
0x29 => '69FFFF',
0x2A => 'E0FFE0',
0x2B => 'FFFF80',
0x2C => 'A6CAF0',
0x2D => 'DD9CB3',
0x2E => 'B38FEE',
0x2F => 'E3E3E3',
0x30 => '2A6FF9',
0x31 => '3FB8CD',
0x32 => '488436',
0x33 => '958C41',
0x34 => '8E5E42',
0x35 => 'A0627A',
0x36 => '624FAC',
0x37 => '969696',
0x38 => '1D2FBE',
0x39 => '286676',
0x3A => '004500',
0x3B => '453E01',
0x3C => '6A2813',
0x3D => '85396A',
0x3E => '4A3285',
0x3F => '424242',
);
/**
* Map color array from BIFF5 built-in color index
*
* @param int $color
* @return array
*/
public static function lookup($color)
{
if (isset(self::$map[$color])) {
return array('rgb' => self::$map[$color]);
}
return array('rgb' => '000000');
}
}

77
extend/PHPExcel/PHPExcel/Reader/Excel5/Color/BIFF8.php

@ -0,0 +1,77 @@
<?php
class PHPExcel_Reader_Excel5_Color_BIFF8
{
protected static $map = array(
0x08 => '000000',
0x09 => 'FFFFFF',
0x0A => 'FF0000',
0x0B => '00FF00',
0x0C => '0000FF',
0x0D => 'FFFF00',
0x0E => 'FF00FF',
0x0F => '00FFFF',
0x10 => '800000',
0x11 => '008000',
0x12 => '000080',
0x13 => '808000',
0x14 => '800080',
0x15 => '008080',
0x16 => 'C0C0C0',
0x17 => '808080',
0x18 => '9999FF',
0x19 => '993366',
0x1A => 'FFFFCC',
0x1B => 'CCFFFF',
0x1C => '660066',
0x1D => 'FF8080',
0x1E => '0066CC',
0x1F => 'CCCCFF',
0x20 => '000080',
0x21 => 'FF00FF',
0x22 => 'FFFF00',
0x23 => '00FFFF',
0x24 => '800080',
0x25 => '800000',
0x26 => '008080',
0x27 => '0000FF',
0x28 => '00CCFF',
0x29 => 'CCFFFF',
0x2A => 'CCFFCC',
0x2B => 'FFFF99',
0x2C => '99CCFF',
0x2D => 'FF99CC',
0x2E => 'CC99FF',
0x2F => 'FFCC99',
0x30 => '3366FF',
0x31 => '33CCCC',
0x32 => '99CC00',
0x33 => 'FFCC00',
0x34 => 'FF9900',
0x35 => 'FF6600',
0x36 => '666699',
0x37 => '969696',
0x38 => '003366',
0x39 => '339966',
0x3A => '003300',
0x3B => '333300',
0x3C => '993300',
0x3D => '993366',
0x3E => '333399',
0x3F => '333333',
);
/**
* Map color array from BIFF8 built-in color index
*
* @param int $color
* @return array
*/
public static function lookup($color)
{
if (isset(self::$map[$color])) {
return array('rgb' => self::$map[$color]);
}
return array('rgb' => '000000');
}
}

31
extend/PHPExcel/PHPExcel/Reader/Excel5/Color/BuiltIn.php

@ -0,0 +1,31 @@
<?php
class PHPExcel_Reader_Excel5_Color_BuiltIn
{
protected static $map = array(
0x00 => '000000',
0x01 => 'FFFFFF',
0x02 => 'FF0000',
0x03 => '00FF00',
0x04 => '0000FF',
0x05 => 'FFFF00',
0x06 => 'FF00FF',
0x07 => '00FFFF',
0x40 => '000000', // system window text color
0x41 => 'FFFFFF', // system window background color
);
/**
* Map built-in color to RGB value
*
* @param int $color Indexed color
* @return array
*/
public static function lookup($color)
{
if (isset(self::$map[$color])) {
return array('rgb' => self::$map[$color]);
}
return array('rgb' => '000000');
}
}

28
extend/PHPExcel/PHPExcel/Reader/Excel5/ErrorCode.php

@ -0,0 +1,28 @@
<?php
class PHPExcel_Reader_Excel5_ErrorCode
{
protected static $map = array(
0x00 => '#NULL!',
0x07 => '#DIV/0!',
0x0F => '#VALUE!',
0x17 => '#REF!',
0x1D => '#NAME?',
0x24 => '#NUM!',
0x2A => '#N/A',
);
/**
* Map error code, e.g. '#N/A'
*
* @param int $code
* @return string
*/
public static function lookup($code)
{
if (isset(self::$map[$code])) {
return self::$map[$code];
}
return false;
}
}

669
extend/PHPExcel/PHPExcel/Reader/Excel5/Escher.php

@ -0,0 +1,669 @@
<?php
/**
* PHPExcel_Reader_Excel5_Escher
*
* Copyright (c) 2006 - 2015 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_Reader_Excel5
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_Excel5_Escher
{
const DGGCONTAINER = 0xF000;
const BSTORECONTAINER = 0xF001;
const DGCONTAINER = 0xF002;
const SPGRCONTAINER = 0xF003;
const SPCONTAINER = 0xF004;
const DGG = 0xF006;
const BSE = 0xF007;
const DG = 0xF008;
const SPGR = 0xF009;
const SP = 0xF00A;
const OPT = 0xF00B;
const CLIENTTEXTBOX = 0xF00D;
const CLIENTANCHOR = 0xF010;
const CLIENTDATA = 0xF011;
const BLIPJPEG = 0xF01D;
const BLIPPNG = 0xF01E;
const SPLITMENUCOLORS = 0xF11E;
const TERTIARYOPT = 0xF122;
/**
* Escher stream data (binary)
*
* @var string
*/
private $data;
/**
* Size in bytes of the Escher stream data
*
* @var int
*/
private $dataSize;
/**
* Current position of stream pointer in Escher stream data
*
* @var int
*/
private $pos;
/**
* The object to be returned by the reader. Modified during load.
*
* @var mixed
*/
private $object;
/**
* Create a new PHPExcel_Reader_Excel5_Escher instance
*
* @param mixed $object
*/
public function __construct($object)
{
$this->object = $object;
}
/**
* Load Escher stream data. May be a partial Escher stream.
*
* @param string $data
*/
public function load($data)
{
$this->data = $data;
// total byte size of Excel data (workbook global substream + sheet substreams)
$this->dataSize = strlen($this->data);
$this->pos = 0;
// Parse Escher stream
while ($this->pos < $this->dataSize) {
// offset: 2; size: 2: Record Type
$fbt = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos + 2);
switch ($fbt) {
case self::DGGCONTAINER:
$this->readDggContainer();
break;
case self::DGG:
$this->readDgg();
break;
case self::BSTORECONTAINER:
$this->readBstoreContainer();
break;
case self::BSE:
$this->readBSE();
break;
case self::BLIPJPEG:
$this->readBlipJPEG();
break;
case self::BLIPPNG:
$this->readBlipPNG();
break;
case self::OPT:
$this->readOPT();
break;
case self::TERTIARYOPT:
$this->readTertiaryOPT();
break;
case self::SPLITMENUCOLORS:
$this->readSplitMenuColors();
break;
case self::DGCONTAINER:
$this->readDgContainer();
break;
case self::DG:
$this->readDg();
break;
case self::SPGRCONTAINER:
$this->readSpgrContainer();
break;
case self::SPCONTAINER:
$this->readSpContainer();
break;
case self::SPGR:
$this->readSpgr();
break;
case self::SP:
$this->readSp();
break;
case self::CLIENTTEXTBOX:
$this->readClientTextbox();
break;
case self::CLIENTANCHOR:
$this->readClientAnchor();
break;
case self::CLIENTDATA:
$this->readClientData();
break;
default:
$this->readDefault();
break;
}
}
return $this->object;
}
/**
* Read a generic record
*/
private function readDefault()
{
// offset 0; size: 2; recVer and recInstance
$verInstance = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos);
// offset: 2; size: 2: Record Type
$fbt = PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos + 2);
// bit: 0-3; mask: 0x000F; recVer
$recVer = (0x000F & $verInstance) >> 0;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read DggContainer record (Drawing Group Container)
*/
private function readDggContainer()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
// record is a container, read contents
$dggContainer = new PHPExcel_Shared_Escher_DggContainer();
$this->object->setDggContainer($dggContainer);
$reader = new PHPExcel_Reader_Excel5_Escher($dggContainer);
$reader->load($recordData);
}
/**
* Read Dgg record (Drawing Group)
*/
private function readDgg()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read BstoreContainer record (Blip Store Container)
*/
private function readBstoreContainer()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
// record is a container, read contents
$bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer();
$this->object->setBstoreContainer($bstoreContainer);
$reader = new PHPExcel_Reader_Excel5_Escher($bstoreContainer);
$reader->load($recordData);
}
/**
* Read BSE record
*/
private function readBSE()
{
// offset: 0; size: 2; recVer and recInstance
// bit: 4-15; mask: 0xFFF0; recInstance
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
// add BSE to BstoreContainer
$BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE();
$this->object->addBSE($BSE);
$BSE->setBLIPType($recInstance);
// offset: 0; size: 1; btWin32 (MSOBLIPTYPE)
$btWin32 = ord($recordData[0]);
// offset: 1; size: 1; btWin32 (MSOBLIPTYPE)
$btMacOS = ord($recordData[1]);
// offset: 2; size: 16; MD4 digest
$rgbUid = substr($recordData, 2, 16);
// offset: 18; size: 2; tag
$tag = PHPExcel_Reader_Excel5::getInt2d($recordData, 18);
// offset: 20; size: 4; size of BLIP in bytes
$size = PHPExcel_Reader_Excel5::getInt4d($recordData, 20);
// offset: 24; size: 4; number of references to this BLIP
$cRef = PHPExcel_Reader_Excel5::getInt4d($recordData, 24);
// offset: 28; size: 4; MSOFO file offset
$foDelay = PHPExcel_Reader_Excel5::getInt4d($recordData, 28);
// offset: 32; size: 1; unused1
$unused1 = ord($recordData{32});
// offset: 33; size: 1; size of nameData in bytes (including null terminator)
$cbName = ord($recordData{33});
// offset: 34; size: 1; unused2
$unused2 = ord($recordData{34});
// offset: 35; size: 1; unused3
$unused3 = ord($recordData{35});
// offset: 36; size: $cbName; nameData
$nameData = substr($recordData, 36, $cbName);
// offset: 36 + $cbName, size: var; the BLIP data
$blipData = substr($recordData, 36 + $cbName);
// record is a container, read contents
$reader = new PHPExcel_Reader_Excel5_Escher($BSE);
$reader->load($blipData);
}
/**
* Read BlipJPEG record. Holds raw JPEG image data
*/
private function readBlipJPEG()
{
// offset: 0; size: 2; recVer and recInstance
// bit: 4-15; mask: 0xFFF0; recInstance
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
$pos = 0;
// offset: 0; size: 16; rgbUid1 (MD4 digest of)
$rgbUid1 = substr($recordData, 0, 16);
$pos += 16;
// offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3
if (in_array($recInstance, array(0x046B, 0x06E3))) {
$rgbUid2 = substr($recordData, 16, 16);
$pos += 16;
}
// offset: var; size: 1; tag
$tag = ord($recordData{$pos});
$pos += 1;
// offset: var; size: var; the raw image data
$data = substr($recordData, $pos);
$blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip();
$blip->setData($data);
$this->object->setBlip($blip);
}
/**
* Read BlipPNG record. Holds raw PNG image data
*/
private function readBlipPNG()
{
// offset: 0; size: 2; recVer and recInstance
// bit: 4-15; mask: 0xFFF0; recInstance
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
$pos = 0;
// offset: 0; size: 16; rgbUid1 (MD4 digest of)
$rgbUid1 = substr($recordData, 0, 16);
$pos += 16;
// offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3
if ($recInstance == 0x06E1) {
$rgbUid2 = substr($recordData, 16, 16);
$pos += 16;
}
// offset: var; size: 1; tag
$tag = ord($recordData{$pos});
$pos += 1;
// offset: var; size: var; the raw image data
$data = substr($recordData, $pos);
$blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip();
$blip->setData($data);
$this->object->setBlip($blip);
}
/**
* Read OPT record. This record may occur within DggContainer record or SpContainer
*/
private function readOPT()
{
// offset: 0; size: 2; recVer and recInstance
// bit: 4-15; mask: 0xFFF0; recInstance
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
$this->readOfficeArtRGFOPTE($recordData, $recInstance);
}
/**
* Read TertiaryOPT record
*/
private function readTertiaryOPT()
{
// offset: 0; size: 2; recVer and recInstance
// bit: 4-15; mask: 0xFFF0; recInstance
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read SplitMenuColors record
*/
private function readSplitMenuColors()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read DgContainer record (Drawing Container)
*/
private function readDgContainer()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
// record is a container, read contents
$dgContainer = new PHPExcel_Shared_Escher_DgContainer();
$this->object->setDgContainer($dgContainer);
$reader = new PHPExcel_Reader_Excel5_Escher($dgContainer);
$escher = $reader->load($recordData);
}
/**
* Read Dg record (Drawing)
*/
private function readDg()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read SpgrContainer record (Shape Group Container)
*/
private function readSpgrContainer()
{
// context is either context DgContainer or SpgrContainer
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
// record is a container, read contents
$spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer();
if ($this->object instanceof PHPExcel_Shared_Escher_DgContainer) {
// DgContainer
$this->object->setSpgrContainer($spgrContainer);
} else {
// SpgrContainer
$this->object->addChild($spgrContainer);
}
$reader = new PHPExcel_Reader_Excel5_Escher($spgrContainer);
$escher = $reader->load($recordData);
}
/**
* Read SpContainer record (Shape Container)
*/
private function readSpContainer()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// add spContainer to spgrContainer
$spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
$this->object->addChild($spContainer);
// move stream pointer to next record
$this->pos += 8 + $length;
// record is a container, read contents
$reader = new PHPExcel_Reader_Excel5_Escher($spContainer);
$escher = $reader->load($recordData);
}
/**
* Read Spgr record (Shape Group)
*/
private function readSpgr()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read Sp record (Shape)
*/
private function readSp()
{
// offset: 0; size: 2; recVer and recInstance
// bit: 4-15; mask: 0xFFF0; recInstance
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read ClientTextbox record
*/
private function readClientTextbox()
{
// offset: 0; size: 2; recVer and recInstance
// bit: 4-15; mask: 0xFFF0; recInstance
$recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::getInt2d($this->data, $this->pos)) >> 4;
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read ClientAnchor record. This record holds information about where the shape is anchored in worksheet
*/
private function readClientAnchor()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
// offset: 2; size: 2; upper-left corner column index (0-based)
$c1 = PHPExcel_Reader_Excel5::getInt2d($recordData, 2);
// offset: 4; size: 2; upper-left corner horizontal offset in 1/1024 of column width
$startOffsetX = PHPExcel_Reader_Excel5::getInt2d($recordData, 4);
// offset: 6; size: 2; upper-left corner row index (0-based)
$r1 = PHPExcel_Reader_Excel5::getInt2d($recordData, 6);
// offset: 8; size: 2; upper-left corner vertical offset in 1/256 of row height
$startOffsetY = PHPExcel_Reader_Excel5::getInt2d($recordData, 8);
// offset: 10; size: 2; bottom-right corner column index (0-based)
$c2 = PHPExcel_Reader_Excel5::getInt2d($recordData, 10);
// offset: 12; size: 2; bottom-right corner horizontal offset in 1/1024 of column width
$endOffsetX = PHPExcel_Reader_Excel5::getInt2d($recordData, 12);
// offset: 14; size: 2; bottom-right corner row index (0-based)
$r2 = PHPExcel_Reader_Excel5::getInt2d($recordData, 14);
// offset: 16; size: 2; bottom-right corner vertical offset in 1/256 of row height
$endOffsetY = PHPExcel_Reader_Excel5::getInt2d($recordData, 16);
// set the start coordinates
$this->object->setStartCoordinates(PHPExcel_Cell::stringFromColumnIndex($c1) . ($r1 + 1));
// set the start offsetX
$this->object->setStartOffsetX($startOffsetX);
// set the start offsetY
$this->object->setStartOffsetY($startOffsetY);
// set the end coordinates
$this->object->setEndCoordinates(PHPExcel_Cell::stringFromColumnIndex($c2) . ($r2 + 1));
// set the end offsetX
$this->object->setEndOffsetX($endOffsetX);
// set the end offsetY
$this->object->setEndOffsetY($endOffsetY);
}
/**
* Read ClientData record
*/
private function readClientData()
{
$length = PHPExcel_Reader_Excel5::getInt4d($this->data, $this->pos + 4);
$recordData = substr($this->data, $this->pos + 8, $length);
// move stream pointer to next record
$this->pos += 8 + $length;
}
/**
* Read OfficeArtRGFOPTE table of property-value pairs
*
* @param string $data Binary data
* @param int $n Number of properties
*/
private function readOfficeArtRGFOPTE($data, $n)
{
$splicedComplexData = substr($data, 6 * $n);
// loop through property-value pairs
for ($i = 0; $i < $n; ++$i) {
// read 6 bytes at a time
$fopte = substr($data, 6 * $i, 6);
// offset: 0; size: 2; opid
$opid = PHPExcel_Reader_Excel5::getInt2d($fopte, 0);
// bit: 0-13; mask: 0x3FFF; opid.opid
$opidOpid = (0x3FFF & $opid) >> 0;
// bit: 14; mask 0x4000; 1 = value in op field is BLIP identifier
$opidFBid = (0x4000 & $opid) >> 14;
// bit: 15; mask 0x8000; 1 = this is a complex property, op field specifies size of complex data
$opidFComplex = (0x8000 & $opid) >> 15;
// offset: 2; size: 4; the value for this property
$op = PHPExcel_Reader_Excel5::getInt4d($fopte, 2);
if ($opidFComplex) {
$complexData = substr($splicedComplexData, 0, $op);
$splicedComplexData = substr($splicedComplexData, $op);
// we store string value with complex data
$value = $complexData;
} else {
// we store integer value
$value = $op;
}
$this->object->setOPT($opidOpid, $value);
}
}
}

203
extend/PHPExcel/PHPExcel/Reader/Excel5/MD5.php

@ -0,0 +1,203 @@
<?php
/**
* PHPExcel_Reader_Excel5_MD5
*
* Copyright (c) 2006 - 2015 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_Reader_Excel5
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_Excel5_MD5
{
// Context
private $a;
private $b;
private $c;
private $d;
/**
* MD5 stream constructor
*/
public function __construct()
{
$this->reset();
}
/**
* Reset the MD5 stream context
*/
public function reset()
{
$this->a = 0x67452301;
$this->b = 0xEFCDAB89;
$this->c = 0x98BADCFE;
$this->d = 0x10325476;
}
/**
* Get MD5 stream context
*
* @return string
*/
public function getContext()
{
$s = '';
foreach (array('a', 'b', 'c', 'd') as $i) {
$v = $this->{$i};
$s .= chr($v & 0xff);
$s .= chr(($v >> 8) & 0xff);
$s .= chr(($v >> 16) & 0xff);
$s .= chr(($v >> 24) & 0xff);
}
return $s;
}
/**
* Add data to context
*
* @param string $data Data to add
*/
public function add($data)
{
$words = array_values(unpack('V16', $data));
$A = $this->a;
$B = $this->b;
$C = $this->c;
$D = $this->d;
$F = array('PHPExcel_Reader_Excel5_MD5','f');
$G = array('PHPExcel_Reader_Excel5_MD5','g');
$H = array('PHPExcel_Reader_Excel5_MD5','h');
$I = array('PHPExcel_Reader_Excel5_MD5','i');
/* ROUND 1 */
self::step($F, $A, $B, $C, $D, $words[0], 7, 0xd76aa478);
self::step($F, $D, $A, $B, $C, $words[1], 12, 0xe8c7b756);
self::step($F, $C, $D, $A, $B, $words[2], 17, 0x242070db);
self::step($F, $B, $C, $D, $A, $words[3], 22, 0xc1bdceee);
self::step($F, $A, $B, $C, $D, $words[4], 7, 0xf57c0faf);
self::step($F, $D, $A, $B, $C, $words[5], 12, 0x4787c62a);
self::step($F, $C, $D, $A, $B, $words[6], 17, 0xa8304613);
self::step($F, $B, $C, $D, $A, $words[7], 22, 0xfd469501);
self::step($F, $A, $B, $C, $D, $words[8], 7, 0x698098d8);
self::step($F, $D, $A, $B, $C, $words[9], 12, 0x8b44f7af);
self::step($F, $C, $D, $A, $B, $words[10], 17, 0xffff5bb1);
self::step($F, $B, $C, $D, $A, $words[11], 22, 0x895cd7be);
self::step($F, $A, $B, $C, $D, $words[12], 7, 0x6b901122);
self::step($F, $D, $A, $B, $C, $words[13], 12, 0xfd987193);
self::step($F, $C, $D, $A, $B, $words[14], 17, 0xa679438e);
self::step($F, $B, $C, $D, $A, $words[15], 22, 0x49b40821);
/* ROUND 2 */
self::step($G, $A, $B, $C, $D, $words[1], 5, 0xf61e2562);
self::step($G, $D, $A, $B, $C, $words[6], 9, 0xc040b340);
self::step($G, $C, $D, $A, $B, $words[11], 14, 0x265e5a51);
self::step($G, $B, $C, $D, $A, $words[0], 20, 0xe9b6c7aa);
self::step($G, $A, $B, $C, $D, $words[5], 5, 0xd62f105d);
self::step($G, $D, $A, $B, $C, $words[10], 9, 0x02441453);
self::step($G, $C, $D, $A, $B, $words[15], 14, 0xd8a1e681);
self::step($G, $B, $C, $D, $A, $words[4], 20, 0xe7d3fbc8);
self::step($G, $A, $B, $C, $D, $words[9], 5, 0x21e1cde6);
self::step($G, $D, $A, $B, $C, $words[14], 9, 0xc33707d6);
self::step($G, $C, $D, $A, $B, $words[3], 14, 0xf4d50d87);
self::step($G, $B, $C, $D, $A, $words[8], 20, 0x455a14ed);
self::step($G, $A, $B, $C, $D, $words[13], 5, 0xa9e3e905);
self::step($G, $D, $A, $B, $C, $words[2], 9, 0xfcefa3f8);
self::step($G, $C, $D, $A, $B, $words[7], 14, 0x676f02d9);
self::step($G, $B, $C, $D, $A, $words[12], 20, 0x8d2a4c8a);
/* ROUND 3 */
self::step($H, $A, $B, $C, $D, $words[5], 4, 0xfffa3942);
self::step($H, $D, $A, $B, $C, $words[8], 11, 0x8771f681);
self::step($H, $C, $D, $A, $B, $words[11], 16, 0x6d9d6122);
self::step($H, $B, $C, $D, $A, $words[14], 23, 0xfde5380c);
self::step($H, $A, $B, $C, $D, $words[1], 4, 0xa4beea44);
self::step($H, $D, $A, $B, $C, $words[4], 11, 0x4bdecfa9);
self::step($H, $C, $D, $A, $B, $words[7], 16, 0xf6bb4b60);
self::step($H, $B, $C, $D, $A, $words[10], 23, 0xbebfbc70);
self::step($H, $A, $B, $C, $D, $words[13], 4, 0x289b7ec6);
self::step($H, $D, $A, $B, $C, $words[0], 11, 0xeaa127fa);
self::step($H, $C, $D, $A, $B, $words[3], 16, 0xd4ef3085);
self::step($H, $B, $C, $D, $A, $words[6], 23, 0x04881d05);
self::step($H, $A, $B, $C, $D, $words[9], 4, 0xd9d4d039);
self::step($H, $D, $A, $B, $C, $words[12], 11, 0xe6db99e5);
self::step($H, $C, $D, $A, $B, $words[15], 16, 0x1fa27cf8);
self::step($H, $B, $C, $D, $A, $words[2], 23, 0xc4ac5665);
/* ROUND 4 */
self::step($I, $A, $B, $C, $D, $words[0], 6, 0xf4292244);
self::step($I, $D, $A, $B, $C, $words[7], 10, 0x432aff97);
self::step($I, $C, $D, $A, $B, $words[14], 15, 0xab9423a7);
self::step($I, $B, $C, $D, $A, $words[5], 21, 0xfc93a039);
self::step($I, $A, $B, $C, $D, $words[12], 6, 0x655b59c3);
self::step($I, $D, $A, $B, $C, $words[3], 10, 0x8f0ccc92);
self::step($I, $C, $D, $A, $B, $words[10], 15, 0xffeff47d);
self::step($I, $B, $C, $D, $A, $words[1], 21, 0x85845dd1);
self::step($I, $A, $B, $C, $D, $words[8], 6, 0x6fa87e4f);
self::step($I, $D, $A, $B, $C, $words[15], 10, 0xfe2ce6e0);
self::step($I, $C, $D, $A, $B, $words[6], 15, 0xa3014314);
self::step($I, $B, $C, $D, $A, $words[13], 21, 0x4e0811a1);
self::step($I, $A, $B, $C, $D, $words[4], 6, 0xf7537e82);
self::step($I, $D, $A, $B, $C, $words[11], 10, 0xbd3af235);
self::step($I, $C, $D, $A, $B, $words[2], 15, 0x2ad7d2bb);
self::step($I, $B, $C, $D, $A, $words[9], 21, 0xeb86d391);
$this->a = ($this->a + $A) & 0xffffffff;
$this->b = ($this->b + $B) & 0xffffffff;
$this->c = ($this->c + $C) & 0xffffffff;
$this->d = ($this->d + $D) & 0xffffffff;
}
private static function f($X, $Y, $Z)
{
return (($X & $Y) | ((~ $X) & $Z)); // X AND Y OR NOT X AND Z
}
private static function g($X, $Y, $Z)
{
return (($X & $Z) | ($Y & (~ $Z))); // X AND Z OR Y AND NOT Z
}
private static function h($X, $Y, $Z)
{
return ($X ^ $Y ^ $Z); // X XOR Y XOR Z
}
private static function i($X, $Y, $Z)
{
return ($Y ^ ($X | (~ $Z))) ; // Y XOR (X OR NOT Z)
}
private static function step($func, &$A, $B, $C, $D, $M, $s, $t)
{
$A = ($A + call_user_func($func, $B, $C, $D) + $M + $t) & 0xffffffff;
$A = self::rotate($A, $s);
$A = ($B + $A) & 0xffffffff;
}
private static function rotate($decimal, $bits)
{
$binary = str_pad(decbin($decimal), 32, "0", STR_PAD_LEFT);
return bindec(substr($binary, $bits).substr($binary, 0, $bits));
}
}

81
extend/PHPExcel/PHPExcel/Reader/Excel5/RC4.php

@ -0,0 +1,81 @@
<?php
/**
* PHPExcel_Reader_Excel5_RC4
*
* Copyright (c) 2006 - 2015 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_Reader_Excel5
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_Excel5_RC4
{
// Context
protected $s = array();
protected $i = 0;
protected $j = 0;
/**
* RC4 stream decryption/encryption constrcutor
*
* @param string $key Encryption key/passphrase
*/
public function __construct($key)
{
$len = strlen($key);
for ($this->i = 0; $this->i < 256; $this->i++) {
$this->s[$this->i] = $this->i;
}
$this->j = 0;
for ($this->i = 0; $this->i < 256; $this->i++) {
$this->j = ($this->j + $this->s[$this->i] + ord($key[$this->i % $len])) % 256;
$t = $this->s[$this->i];
$this->s[$this->i] = $this->s[$this->j];
$this->s[$this->j] = $t;
}
$this->i = $this->j = 0;
}
/**
* Symmetric decryption/encryption function
*
* @param string $data Data to encrypt/decrypt
*
* @return string
*/
public function RC4($data)
{
$len = strlen($data);
for ($c = 0; $c < $len; $c++) {
$this->i = ($this->i + 1) % 256;
$this->j = ($this->j + $this->s[$this->i]) % 256;
$t = $this->s[$this->i];
$this->s[$this->i] = $this->s[$this->j];
$this->s[$this->j] = $t;
$t = ($this->s[$this->i] + $this->s[$this->j]) % 256;
$data[$c] = chr(ord($data[$c]) ^ $this->s[$t]);
}
return $data;
}
}

36
extend/PHPExcel/PHPExcel/Reader/Excel5/Style/Border.php

@ -0,0 +1,36 @@
<?php
class PHPExcel_Reader_Excel5_Style_Border
{
protected static $map = array(
0x00 => PHPExcel_Style_Border::BORDER_NONE,
0x01 => PHPExcel_Style_Border::BORDER_THIN,
0x02 => PHPExcel_Style_Border::BORDER_MEDIUM,
0x03 => PHPExcel_Style_Border::BORDER_DASHED,
0x04 => PHPExcel_Style_Border::BORDER_DOTTED,
0x05 => PHPExcel_Style_Border::BORDER_THICK,
0x06 => PHPExcel_Style_Border::BORDER_DOUBLE,
0x07 => PHPExcel_Style_Border::BORDER_HAIR,
0x08 => PHPExcel_Style_Border::BORDER_MEDIUMDASHED,
0x09 => PHPExcel_Style_Border::BORDER_DASHDOT,
0x0A => PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT,
0x0B => PHPExcel_Style_Border::BORDER_DASHDOTDOT,
0x0C => PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT,
0x0D => PHPExcel_Style_Border::BORDER_SLANTDASHDOT,
);
/**
* Map border style
* OpenOffice documentation: 2.5.11
*
* @param int $index
* @return string
*/
public static function lookup($index)
{
if (isset(self::$map[$index])) {
return self::$map[$index];
}
return PHPExcel_Style_Border::BORDER_NONE;
}
}

41
extend/PHPExcel/PHPExcel/Reader/Excel5/Style/FillPattern.php

@ -0,0 +1,41 @@
<?php
class PHPExcel_Reader_Excel5_Style_FillPattern
{
protected static $map = array(
0x00 => PHPExcel_Style_Fill::FILL_NONE,
0x01 => PHPExcel_Style_Fill::FILL_SOLID,
0x02 => PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY,
0x03 => PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY,
0x04 => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY,
0x05 => PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL,
0x06 => PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL,
0x07 => PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN,
0x08 => PHPExcel_Style_Fill::FILL_PATTERN_DARKUP,
0x09 => PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID,
0x0A => PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS,
0x0B => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL,
0x0C => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL,
0x0D => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN,
0x0E => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP,
0x0F => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID,
0x10 => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS,
0x11 => PHPExcel_Style_Fill::FILL_PATTERN_GRAY125,
0x12 => PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625,
);
/**
* Get fill pattern from index
* OpenOffice documentation: 2.5.12
*
* @param int $index
* @return string
*/
public static function lookup($index)
{
if (isset(self::$map[$index])) {
return self::$map[$index];
}
return PHPExcel_Style_Fill::FILL_NONE;
}
}

46
extend/PHPExcel/PHPExcel/Reader/Exception.php

@ -0,0 +1,46 @@
<?php
/**
* PHPExcel_Reader_Exception
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_Exception extends PHPExcel_Exception
{
/**
* Error handler callback
*
* @param mixed $code
* @param mixed $string
* @param mixed $file
* @param mixed $line
* @param mixed $context
*/
public static function errorHandlerCallback($code, $string, $file, $line, $context)
{
$e = new self($string, $code);
$e->line = $line;
$e->file = $file;
throw $e;
}
}

850
extend/PHPExcel/PHPExcel/Reader/Gnumeric.php

@ -0,0 +1,850 @@
<?php
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
/**
* @ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel_Reader_Gnumeric
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_Gnumeric extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
{
/**
* Formats
*
* @var array
*/
private $styles = array();
/**
* Shared Expressions
*
* @var array
*/
private $expressions = array();
private $referenceHelper = null;
/**
* Create a new PHPExcel_Reader_Gnumeric
*/
public function __construct()
{
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter();
$this->referenceHelper = PHPExcel_ReferenceHelper::getInstance();
}
/**
* Can the current PHPExcel_Reader_IReader read the file?
*
* @param string $pFilename
* @return boolean
* @throws PHPExcel_Reader_Exception
*/
public function canRead($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
// Check if gzlib functions are available
if (!function_exists('gzread')) {
throw new PHPExcel_Reader_Exception("gzlib library is not enabled");
}
// Read signature data (first 3 bytes)
$fh = fopen($pFilename, 'r');
$data = fread($fh, 2);
fclose($fh);
if ($data != chr(0x1F).chr(0x8B)) {
return false;
}
return true;
}
/**
* Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetNames($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$xml = new XMLReader();
$xml->xml($this->securityScanFile('compress.zlib://'.realpath($pFilename)), null, PHPExcel_Settings::getLibXmlLoaderOptions());
$xml->setParserProperty(2, true);
$worksheetNames = array();
while ($xml->read()) {
if ($xml->name == 'gnm:SheetName' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$worksheetNames[] = (string) $xml->value;
} elseif ($xml->name == 'gnm:Sheets') {
// break out of the loop once we've got our sheet names rather than parse the entire file
break;
}
}
return $worksheetNames;
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetInfo($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$xml = new XMLReader();
$xml->xml($this->securityScanFile('compress.zlib://'.realpath($pFilename)), null, PHPExcel_Settings::getLibXmlLoaderOptions());
$xml->setParserProperty(2, true);
$worksheetInfo = array();
while ($xml->read()) {
if ($xml->name == 'gnm:Sheet' && $xml->nodeType == XMLReader::ELEMENT) {
$tmpInfo = array(
'worksheetName' => '',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 0,
'totalColumns' => 0,
);
while ($xml->read()) {
if ($xml->name == 'gnm:Name' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$tmpInfo['worksheetName'] = (string) $xml->value;
} elseif ($xml->name == 'gnm:MaxCol' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$tmpInfo['lastColumnIndex'] = (int) $xml->value;
$tmpInfo['totalColumns'] = (int) $xml->value + 1;
} elseif ($xml->name == 'gnm:MaxRow' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$tmpInfo['totalRows'] = (int) $xml->value + 1;
break;
}
}
$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
$worksheetInfo[] = $tmpInfo;
}
}
return $worksheetInfo;
}
private function gzfileGetContents($filename)
{
$file = @gzopen($filename, 'rb');
if ($file !== false) {
$data = '';
while (!gzeof($file)) {
$data .= gzread($file, 1024);
}
gzclose($file);
}
return $data;
}
/**
* Loads PHPExcel from file
*
* @param string $pFilename
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function load($pFilename)
{
// Create new PHPExcel
$objPHPExcel = new PHPExcel();
// Load into this instance
return $this->loadIntoExisting($pFilename, $objPHPExcel);
}
/**
* Loads PHPExcel from file into PHPExcel instance
*
* @param string $pFilename
* @param PHPExcel $objPHPExcel
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$timezoneObj = new DateTimeZone('Europe/London');
$GMT = new DateTimeZone('UTC');
$gFileData = $this->gzfileGetContents($pFilename);
// echo '<pre>';
// echo htmlentities($gFileData,ENT_QUOTES,'UTF-8');
// echo '</pre><hr />';
//
$xml = simplexml_load_string($this->securityScan($gFileData), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
$namespacesMeta = $xml->getNamespaces(true);
// var_dump($namespacesMeta);
//
$gnmXML = $xml->children($namespacesMeta['gnm']);
$docProps = $objPHPExcel->getProperties();
// Document Properties are held differently, depending on the version of Gnumeric
if (isset($namespacesMeta['office'])) {
$officeXML = $xml->children($namespacesMeta['office']);
$officeDocXML = $officeXML->{'document-meta'};
$officeDocMetaXML = $officeDocXML->meta;
foreach ($officeDocMetaXML as $officePropertyData) {
$officePropertyDC = array();
if (isset($namespacesMeta['dc'])) {
$officePropertyDC = $officePropertyData->children($namespacesMeta['dc']);
}
foreach ($officePropertyDC as $propertyName => $propertyValue) {
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'title':
$docProps->setTitle(trim($propertyValue));
break;
case 'subject':
$docProps->setSubject(trim($propertyValue));
break;
case 'creator':
$docProps->setCreator(trim($propertyValue));
$docProps->setLastModifiedBy(trim($propertyValue));
break;
case 'date':
$creationDate = strtotime(trim($propertyValue));
$docProps->setCreated($creationDate);
$docProps->setModified($creationDate);
break;
case 'description':
$docProps->setDescription(trim($propertyValue));
break;
}
}
$officePropertyMeta = array();
if (isset($namespacesMeta['meta'])) {
$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
}
foreach ($officePropertyMeta as $propertyName => $propertyValue) {
$attributes = $propertyValue->attributes($namespacesMeta['meta']);
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'keyword':
$docProps->setKeywords(trim($propertyValue));
break;
case 'initial-creator':
$docProps->setCreator(trim($propertyValue));
$docProps->setLastModifiedBy(trim($propertyValue));
break;
case 'creation-date':
$creationDate = strtotime(trim($propertyValue));
$docProps->setCreated($creationDate);
$docProps->setModified($creationDate);
break;
case 'user-defined':
list(, $attrName) = explode(':', $attributes['name']);
switch ($attrName) {
case 'publisher':
$docProps->setCompany(trim($propertyValue));
break;
case 'category':
$docProps->setCategory(trim($propertyValue));
break;
case 'manager':
$docProps->setManager(trim($propertyValue));
break;
}
break;
}
}
}
} elseif (isset($gnmXML->Summary)) {
foreach ($gnmXML->Summary->Item as $summaryItem) {
$propertyName = $summaryItem->name;
$propertyValue = $summaryItem->{'val-string'};
switch ($propertyName) {
case 'title':
$docProps->setTitle(trim($propertyValue));
break;
case 'comments':
$docProps->setDescription(trim($propertyValue));
break;
case 'keywords':
$docProps->setKeywords(trim($propertyValue));
break;
case 'category':
$docProps->setCategory(trim($propertyValue));
break;
case 'manager':
$docProps->setManager(trim($propertyValue));
break;
case 'author':
$docProps->setCreator(trim($propertyValue));
$docProps->setLastModifiedBy(trim($propertyValue));
break;
case 'company':
$docProps->setCompany(trim($propertyValue));
break;
}
}
}
$worksheetID = 0;
foreach ($gnmXML->Sheets->Sheet as $sheet) {
$worksheetName = (string) $sheet->Name;
// echo '<b>Worksheet: ', $worksheetName,'</b><br />';
if ((isset($this->loadSheetsOnly)) && (!in_array($worksheetName, $this->loadSheetsOnly))) {
continue;
}
$maxRow = $maxCol = 0;
// Create new Worksheet
$objPHPExcel->createSheet();
$objPHPExcel->setActiveSheetIndex($worksheetID);
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in formula
// cells... during the load, all formulae should be correct, and we're simply bringing the worksheet
// name in line with the formula, not the reverse
$objPHPExcel->getActiveSheet()->setTitle($worksheetName, false);
if ((!$this->readDataOnly) && (isset($sheet->PrintInformation))) {
if (isset($sheet->PrintInformation->Margins)) {
foreach ($sheet->PrintInformation->Margins->children('gnm', true) as $key => $margin) {
$marginAttributes = $margin->attributes();
$marginSize = 72 / 100; // Default
switch ($marginAttributes['PrefUnit']) {
case 'mm':
$marginSize = intval($marginAttributes['Points']) / 100;
break;
}
switch ($key) {
case 'top':
$objPHPExcel->getActiveSheet()->getPageMargins()->setTop($marginSize);
break;
case 'bottom':
$objPHPExcel->getActiveSheet()->getPageMargins()->setBottom($marginSize);
break;
case 'left':
$objPHPExcel->getActiveSheet()->getPageMargins()->setLeft($marginSize);
break;
case 'right':
$objPHPExcel->getActiveSheet()->getPageMargins()->setRight($marginSize);
break;
case 'header':
$objPHPExcel->getActiveSheet()->getPageMargins()->setHeader($marginSize);
break;
case 'footer':
$objPHPExcel->getActiveSheet()->getPageMargins()->setFooter($marginSize);
break;
}
}
}
}
foreach ($sheet->Cells->Cell as $cell) {
$cellAttributes = $cell->attributes();
$row = (int) $cellAttributes->Row + 1;
$column = (int) $cellAttributes->Col;
if ($row > $maxRow) {
$maxRow = $row;
}
if ($column > $maxCol) {
$maxCol = $column;
}
$column = PHPExcel_Cell::stringFromColumnIndex($column);
// Read cell?
if ($this->getReadFilter() !== null) {
if (!$this->getReadFilter()->readCell($column, $row, $worksheetName)) {
continue;
}
}
$ValueType = $cellAttributes->ValueType;
$ExprID = (string) $cellAttributes->ExprID;
// echo 'Cell ', $column, $row,'<br />';
// echo 'Type is ', $ValueType,'<br />';
// echo 'Value is ', $cell,'<br />';
$type = PHPExcel_Cell_DataType::TYPE_FORMULA;
if ($ExprID > '') {
if (((string) $cell) > '') {
$this->expressions[$ExprID] = array(
'column' => $cellAttributes->Col,
'row' => $cellAttributes->Row,
'formula' => (string) $cell
);
// echo 'NEW EXPRESSION ', $ExprID,'<br />';
} else {
$expression = $this->expressions[$ExprID];
$cell = $this->referenceHelper->updateFormulaReferences(
$expression['formula'],
'A1',
$cellAttributes->Col - $expression['column'],
$cellAttributes->Row - $expression['row'],
$worksheetName
);
// echo 'SHARED EXPRESSION ', $ExprID,'<br />';
// echo 'New Value is ', $cell,'<br />';
}
$type = PHPExcel_Cell_DataType::TYPE_FORMULA;
} else {
switch ($ValueType) {
case '10': // NULL
$type = PHPExcel_Cell_DataType::TYPE_NULL;
break;
case '20': // Boolean
$type = PHPExcel_Cell_DataType::TYPE_BOOL;
$cell = ($cell == 'TRUE') ? true: false;
break;
case '30': // Integer
$cell = intval($cell);
// Excel 2007+ doesn't differentiate between integer and float, so set the value and dropthru to the next (numeric) case
case '40': // Float
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
break;
case '50': // Error
$type = PHPExcel_Cell_DataType::TYPE_ERROR;
break;
case '60': // String
$type = PHPExcel_Cell_DataType::TYPE_STRING;
break;
case '70': // Cell Range
case '80': // Array
}
}
$objPHPExcel->getActiveSheet()->getCell($column.$row)->setValueExplicit($cell, $type);
}
if ((!$this->readDataOnly) && (isset($sheet->Objects))) {
foreach ($sheet->Objects->children('gnm', true) as $key => $comment) {
$commentAttributes = $comment->attributes();
// Only comment objects are handled at the moment
if ($commentAttributes->Text) {
$objPHPExcel->getActiveSheet()->getComment((string)$commentAttributes->ObjectBound)->setAuthor((string)$commentAttributes->Author)->setText($this->parseRichText((string)$commentAttributes->Text));
}
}
}
// echo '$maxCol=', $maxCol,'; $maxRow=', $maxRow,'<br />';
//
foreach ($sheet->Styles->StyleRegion as $styleRegion) {
$styleAttributes = $styleRegion->attributes();
if (($styleAttributes['startRow'] <= $maxRow) &&
($styleAttributes['startCol'] <= $maxCol)) {
$startColumn = PHPExcel_Cell::stringFromColumnIndex((int) $styleAttributes['startCol']);
$startRow = $styleAttributes['startRow'] + 1;
$endColumn = ($styleAttributes['endCol'] > $maxCol) ? $maxCol : (int) $styleAttributes['endCol'];
$endColumn = PHPExcel_Cell::stringFromColumnIndex($endColumn);
$endRow = ($styleAttributes['endRow'] > $maxRow) ? $maxRow : $styleAttributes['endRow'];
$endRow += 1;
$cellRange = $startColumn.$startRow.':'.$endColumn.$endRow;
// echo $cellRange,'<br />';
$styleAttributes = $styleRegion->Style->attributes();
// var_dump($styleAttributes);
// echo '<br />';
// We still set the number format mask for date/time values, even if readDataOnly is true
if ((!$this->readDataOnly) ||
(PHPExcel_Shared_Date::isDateTimeFormatCode((string) $styleAttributes['Format']))) {
$styleArray = array();
$styleArray['numberformat']['code'] = (string) $styleAttributes['Format'];
// If readDataOnly is false, we set all formatting information
if (!$this->readDataOnly) {
switch ($styleAttributes['HAlign']) {
case '1':
$styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL;
break;
case '2':
$styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_LEFT;
break;
case '4':
$styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_RIGHT;
break;
case '8':
$styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER;
break;
case '16':
case '64':
$styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS;
break;
case '32':
$styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY;
break;
}
switch ($styleAttributes['VAlign']) {
case '1':
$styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_TOP;
break;
case '2':
$styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_BOTTOM;
break;
case '4':
$styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_CENTER;
break;
case '8':
$styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_JUSTIFY;
break;
}
$styleArray['alignment']['wrap'] = ($styleAttributes['WrapText'] == '1') ? true : false;
$styleArray['alignment']['shrinkToFit'] = ($styleAttributes['ShrinkToFit'] == '1') ? true : false;
$styleArray['alignment']['indent'] = (intval($styleAttributes["Indent"]) > 0) ? $styleAttributes["indent"] : 0;
$RGB = self::parseGnumericColour($styleAttributes["Fore"]);
$styleArray['font']['color']['rgb'] = $RGB;
$RGB = self::parseGnumericColour($styleAttributes["Back"]);
$shade = $styleAttributes["Shade"];
if (($RGB != '000000') || ($shade != '0')) {
$styleArray['fill']['color']['rgb'] = $styleArray['fill']['startcolor']['rgb'] = $RGB;
$RGB2 = self::parseGnumericColour($styleAttributes["PatternColor"]);
$styleArray['fill']['endcolor']['rgb'] = $RGB2;
switch ($shade) {
case '1':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_SOLID;
break;
case '2':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR;
break;
case '3':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_PATH;
break;
case '4':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN;
break;
case '5':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY;
break;
case '6':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID;
break;
case '7':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL;
break;
case '8':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS;
break;
case '9':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKUP;
break;
case '10':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL;
break;
case '11':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625;
break;
case '12':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY125;
break;
case '13':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN;
break;
case '14':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY;
break;
case '15':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID;
break;
case '16':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL;
break;
case '17':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS;
break;
case '18':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP;
break;
case '19':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL;
break;
case '20':
$styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY;
break;
}
}
$fontAttributes = $styleRegion->Style->Font->attributes();
// var_dump($fontAttributes);
// echo '<br />';
$styleArray['font']['name'] = (string) $styleRegion->Style->Font;
$styleArray['font']['size'] = intval($fontAttributes['Unit']);
$styleArray['font']['bold'] = ($fontAttributes['Bold'] == '1') ? true : false;
$styleArray['font']['italic'] = ($fontAttributes['Italic'] == '1') ? true : false;
$styleArray['font']['strike'] = ($fontAttributes['StrikeThrough'] == '1') ? true : false;
switch ($fontAttributes['Underline']) {
case '1':
$styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLE;
break;
case '2':
$styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLE;
break;
case '3':
$styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING;
break;
case '4':
$styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING;
break;
default:
$styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_NONE;
break;
}
switch ($fontAttributes['Script']) {
case '1':
$styleArray['font']['superScript'] = true;
break;
case '-1':
$styleArray['font']['subScript'] = true;
break;
}
if (isset($styleRegion->Style->StyleBorder)) {
if (isset($styleRegion->Style->StyleBorder->Top)) {
$styleArray['borders']['top'] = self::parseBorderAttributes($styleRegion->Style->StyleBorder->Top->attributes());
}
if (isset($styleRegion->Style->StyleBorder->Bottom)) {
$styleArray['borders']['bottom'] = self::parseBorderAttributes($styleRegion->Style->StyleBorder->Bottom->attributes());
}
if (isset($styleRegion->Style->StyleBorder->Left)) {
$styleArray['borders']['left'] = self::parseBorderAttributes($styleRegion->Style->StyleBorder->Left->attributes());
}
if (isset($styleRegion->Style->StyleBorder->Right)) {
$styleArray['borders']['right'] = self::parseBorderAttributes($styleRegion->Style->StyleBorder->Right->attributes());
}
if ((isset($styleRegion->Style->StyleBorder->Diagonal)) && (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}))) {
$styleArray['borders']['diagonal'] = self::parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes());
$styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_BOTH;
} elseif (isset($styleRegion->Style->StyleBorder->Diagonal)) {
$styleArray['borders']['diagonal'] = self::parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes());
$styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_UP;
} elseif (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'})) {
$styleArray['borders']['diagonal'] = self::parseBorderAttributes($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}->attributes());
$styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_DOWN;
}
}
if (isset($styleRegion->Style->HyperLink)) {
// TO DO
$hyperlink = $styleRegion->Style->HyperLink->attributes();
}
}
// var_dump($styleArray);
// echo '<br />';
$objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($styleArray);
}
}
}
if ((!$this->readDataOnly) && (isset($sheet->Cols))) {
// Column Widths
$columnAttributes = $sheet->Cols->attributes();
$defaultWidth = $columnAttributes['DefaultSizePts'] / 5.4;
$c = 0;
foreach ($sheet->Cols->ColInfo as $columnOverride) {
$columnAttributes = $columnOverride->attributes();
$column = $columnAttributes['No'];
$columnWidth = $columnAttributes['Unit'] / 5.4;
$hidden = ((isset($columnAttributes['Hidden'])) && ($columnAttributes['Hidden'] == '1')) ? true : false;
$columnCount = (isset($columnAttributes['Count'])) ? $columnAttributes['Count'] : 1;
while ($c < $column) {
$objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth);
++$c;
}
while (($c < ($column+$columnCount)) && ($c <= $maxCol)) {
$objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($columnWidth);
if ($hidden) {
$objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setVisible(false);
}
++$c;
}
}
while ($c <= $maxCol) {
$objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth);
++$c;
}
}
if ((!$this->readDataOnly) && (isset($sheet->Rows))) {
// Row Heights
$rowAttributes = $sheet->Rows->attributes();
$defaultHeight = $rowAttributes['DefaultSizePts'];
$r = 0;
foreach ($sheet->Rows->RowInfo as $rowOverride) {
$rowAttributes = $rowOverride->attributes();
$row = $rowAttributes['No'];
$rowHeight = $rowAttributes['Unit'];
$hidden = ((isset($rowAttributes['Hidden'])) && ($rowAttributes['Hidden'] == '1')) ? true : false;
$rowCount = (isset($rowAttributes['Count'])) ? $rowAttributes['Count'] : 1;
while ($r < $row) {
++$r;
$objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight);
}
while (($r < ($row+$rowCount)) && ($r < $maxRow)) {
++$r;
$objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($rowHeight);
if ($hidden) {
$objPHPExcel->getActiveSheet()->getRowDimension($r)->setVisible(false);
}
}
}
while ($r < $maxRow) {
++$r;
$objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight);
}
}
// Handle Merged Cells in this worksheet
if (isset($sheet->MergedRegions)) {
foreach ($sheet->MergedRegions->Merge as $mergeCells) {
if (strpos($mergeCells, ':') !== false) {
$objPHPExcel->getActiveSheet()->mergeCells($mergeCells);
}
}
}
$worksheetID++;
}
// Loop through definedNames (global named ranges)
if (isset($gnmXML->Names)) {
foreach ($gnmXML->Names->Name as $namedRange) {
$name = (string) $namedRange->name;
$range = (string) $namedRange->value;
if (stripos($range, '#REF!') !== false) {
continue;
}
$range = explode('!', $range);
$range[0] = trim($range[0], "'");
if ($worksheet = $objPHPExcel->getSheetByName($range[0])) {
$extractedRange = str_replace('$', '', $range[1]);
$objPHPExcel->addNamedRange(new PHPExcel_NamedRange($name, $worksheet, $extractedRange));
}
}
}
// Return
return $objPHPExcel;
}
private static function parseBorderAttributes($borderAttributes)
{
$styleArray = array();
if (isset($borderAttributes["Color"])) {
$styleArray['color']['rgb'] = self::parseGnumericColour($borderAttributes["Color"]);
}
switch ($borderAttributes["Style"]) {
case '0':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_NONE;
break;
case '1':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
case '2':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUM;
break;
case '3':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_SLANTDASHDOT;
break;
case '4':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHED;
break;
case '5':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_THICK;
break;
case '6':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_DOUBLE;
break;
case '7':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_DOTTED;
break;
case '8':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHED;
break;
case '9':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOT;
break;
case '10':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT;
break;
case '11':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOTDOT;
break;
case '12':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT;
break;
case '13':
$styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT;
break;
}
return $styleArray;
}
private function parseRichText($is = '')
{
$value = new PHPExcel_RichText();
$value->createText($is);
return $value;
}
private static function parseGnumericColour($gnmColour)
{
list($gnmR, $gnmG, $gnmB) = explode(':', $gnmColour);
$gnmR = substr(str_pad($gnmR, 4, '0', STR_PAD_RIGHT), 0, 2);
$gnmG = substr(str_pad($gnmG, 4, '0', STR_PAD_RIGHT), 0, 2);
$gnmB = substr(str_pad($gnmB, 4, '0', STR_PAD_RIGHT), 0, 2);
return $gnmR . $gnmG . $gnmB;
}
}

549
extend/PHPExcel/PHPExcel/Reader/HTML.php

@ -0,0 +1,549 @@
<?php
if (!defined('PHPEXCEL_ROOT')) {
/**
* @ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel_Reader_HTML
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/** PHPExcel root directory */
class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
{
/**
* Input encoding
*
* @var string
*/
protected $inputEncoding = 'ANSI';
/**
* Sheet index to read
*
* @var int
*/
protected $sheetIndex = 0;
/**
* Formats
*
* @var array
*/
protected $formats = array(
'h1' => array(
'font' => array(
'bold' => true,
'size' => 24,
),
), // Bold, 24pt
'h2' => array(
'font' => array(
'bold' => true,
'size' => 18,
),
), // Bold, 18pt
'h3' => array(
'font' => array(
'bold' => true,
'size' => 13.5,
),
), // Bold, 13.5pt
'h4' => array(
'font' => array(
'bold' => true,
'size' => 12,
),
), // Bold, 12pt
'h5' => array(
'font' => array(
'bold' => true,
'size' => 10,
),
), // Bold, 10pt
'h6' => array(
'font' => array(
'bold' => true,
'size' => 7.5,
),
), // Bold, 7.5pt
'a' => array(
'font' => array(
'underline' => true,
'color' => array(
'argb' => PHPExcel_Style_Color::COLOR_BLUE,
),
),
), // Blue underlined
'hr' => array(
'borders' => array(
'bottom' => array(
'style' => PHPExcel_Style_Border::BORDER_THIN,
'color' => array(
PHPExcel_Style_Color::COLOR_BLACK,
),
),
),
), // Bottom border
);
protected $rowspan = array();
/**
* Create a new PHPExcel_Reader_HTML
*/
public function __construct()
{
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter();
}
/**
* Validate that the current file is an HTML file
*
* @return boolean
*/
protected function isValidFormat()
{
// Reading 2048 bytes should be enough to validate that the format is HTML
$data = fread($this->fileHandle, 2048);
if ((strpos($data, '<') !== false) &&
(strlen($data) !== strlen(strip_tags($data)))) {
return true;
}
return false;
}
/**
* Loads PHPExcel from file
*
* @param string $pFilename
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function load($pFilename)
{
// Create new PHPExcel
$objPHPExcel = new PHPExcel();
// Load into this instance
return $this->loadIntoExisting($pFilename, $objPHPExcel);
}
/**
* Set input encoding
*
* @param string $pValue Input encoding
*/
public function setInputEncoding($pValue = 'ANSI')
{
$this->inputEncoding = $pValue;
return $this;
}
/**
* Get input encoding
*
* @return string
*/
public function getInputEncoding()
{
return $this->inputEncoding;
}
// Data Array used for testing only, should write to PHPExcel object on completion of tests
protected $dataArray = array();
protected $tableLevel = 0;
protected $nestedColumn = array('A');
protected function setTableStartColumn($column)
{
if ($this->tableLevel == 0) {
$column = 'A';
}
++$this->tableLevel;
$this->nestedColumn[$this->tableLevel] = $column;
return $this->nestedColumn[$this->tableLevel];
}
protected function getTableStartColumn()
{
return $this->nestedColumn[$this->tableLevel];
}
protected function releaseTableStartColumn()
{
--$this->tableLevel;
return array_pop($this->nestedColumn);
}
protected function flushCell($sheet, $column, $row, &$cellContent)
{
if (is_string($cellContent)) {
// Simple String content
if (trim($cellContent) > '') {
// Only actually write it if there's content in the string
// echo 'FLUSH CELL: ' , $column , $row , ' => ' , $cellContent , '<br />';
// Write to worksheet to be done here...
// ... we return the cell so we can mess about with styles more easily
$sheet->setCellValue($column . $row, $cellContent, true);
$this->dataArray[$row][$column] = $cellContent;
}
} else {
// We have a Rich Text run
// TODO
$this->dataArray[$row][$column] = 'RICH TEXT: ' . $cellContent;
}
$cellContent = (string) '';
}
protected function processDomElement(DOMNode $element, $sheet, &$row, &$column, &$cellContent, $format = null)
{
foreach ($element->childNodes as $child) {
if ($child instanceof DOMText) {
$domText = preg_replace('/\s+/u', ' ', trim($child->nodeValue));
if (is_string($cellContent)) {
// simply append the text if the cell content is a plain text string
$cellContent .= $domText;
} else {
// but if we have a rich text run instead, we need to append it correctly
// TODO
}
} elseif ($child instanceof DOMElement) {
// echo '<b>DOM ELEMENT: </b>' , strtoupper($child->nodeName) , '<br />';
$attributeArray = array();
foreach ($child->attributes as $attribute) {
// echo '<b>ATTRIBUTE: </b>' , $attribute->name , ' => ' , $attribute->value , '<br />';
$attributeArray[$attribute->name] = $attribute->value;
}
switch ($child->nodeName) {
case 'meta':
foreach ($attributeArray as $attributeName => $attributeValue) {
switch ($attributeName) {
case 'content':
// TODO
// Extract character set, so we can convert to UTF-8 if required
break;
}
}
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
break;
case 'title':
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
$sheet->setTitle($cellContent);
$cellContent = '';
break;
case 'span':
case 'div':
case 'font':
case 'i':
case 'em':
case 'strong':
case 'b':
// echo 'STYLING, SPAN OR DIV<br />';
if ($cellContent > '') {
$cellContent .= ' ';
}
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
if ($cellContent > '') {
$cellContent .= ' ';
}
// echo 'END OF STYLING, SPAN OR DIV<br />';
break;
case 'hr':
$this->flushCell($sheet, $column, $row, $cellContent);
++$row;
if (isset($this->formats[$child->nodeName])) {
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
} else {
$cellContent = '----------';
$this->flushCell($sheet, $column, $row, $cellContent);
}
++$row;
// Add a break after a horizontal rule, simply by allowing the code to dropthru
case 'br':
if ($this->tableLevel > 0) {
// If we're inside a table, replace with a \n
$cellContent .= "\n";
} else {
// Otherwise flush our existing content and move the row cursor on
$this->flushCell($sheet, $column, $row, $cellContent);
++$row;
}
// echo 'HARD LINE BREAK: ' , '<br />';
break;
case 'a':
// echo 'START OF HYPERLINK: ' , '<br />';
foreach ($attributeArray as $attributeName => $attributeValue) {
switch ($attributeName) {
case 'href':
// echo 'Link to ' , $attributeValue , '<br />';
$sheet->getCell($column . $row)->getHyperlink()->setUrl($attributeValue);
if (isset($this->formats[$child->nodeName])) {
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
}
break;
}
}
$cellContent .= ' ';
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
// echo 'END OF HYPERLINK:' , '<br />';
break;
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6':
case 'ol':
case 'ul':
case 'p':
if ($this->tableLevel > 0) {
// If we're inside a table, replace with a \n
$cellContent .= "\n";
// echo 'LIST ENTRY: ' , '<br />';
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
// echo 'END OF LIST ENTRY:' , '<br />';
} else {
if ($cellContent > '') {
$this->flushCell($sheet, $column, $row, $cellContent);
$row++;
}
// echo 'START OF PARAGRAPH: ' , '<br />';
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
// echo 'END OF PARAGRAPH:' , '<br />';
$this->flushCell($sheet, $column, $row, $cellContent);
if (isset($this->formats[$child->nodeName])) {
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
}
$row++;
$column = 'A';
}
break;
case 'li':
if ($this->tableLevel > 0) {
// If we're inside a table, replace with a \n
$cellContent .= "\n";
// echo 'LIST ENTRY: ' , '<br />';
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
// echo 'END OF LIST ENTRY:' , '<br />';
} else {
if ($cellContent > '') {
$this->flushCell($sheet, $column, $row, $cellContent);
}
++$row;
// echo 'LIST ENTRY: ' , '<br />';
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
// echo 'END OF LIST ENTRY:' , '<br />';
$this->flushCell($sheet, $column, $row, $cellContent);
$column = 'A';
}
break;
case 'table':
$this->flushCell($sheet, $column, $row, $cellContent);
$column = $this->setTableStartColumn($column);
// echo 'START OF TABLE LEVEL ' , $this->tableLevel , '<br />';
if ($this->tableLevel > 1) {
--$row;
}
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
// echo 'END OF TABLE LEVEL ' , $this->tableLevel , '<br />';
$column = $this->releaseTableStartColumn();
if ($this->tableLevel > 1) {
++$column;
} else {
++$row;
}
break;
case 'thead':
case 'tbody':
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
break;
case 'tr':
$column = $this->getTableStartColumn();
$cellContent = '';
// echo 'START OF TABLE ' , $this->tableLevel , ' ROW<br />';
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
++$row;
// echo 'END OF TABLE ' , $this->tableLevel , ' ROW<br />';
break;
case 'th':
case 'td':
// echo 'START OF TABLE ' , $this->tableLevel , ' CELL<br />';
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
// echo 'END OF TABLE ' , $this->tableLevel , ' CELL<br />';
while (isset($this->rowspan[$column . $row])) {
++$column;
}
$this->flushCell($sheet, $column, $row, $cellContent);
// if (isset($attributeArray['style']) && !empty($attributeArray['style'])) {
// $styleAry = $this->getPhpExcelStyleArray($attributeArray['style']);
//
// if (!empty($styleAry)) {
// $sheet->getStyle($column . $row)->applyFromArray($styleAry);
// }
// }
if (isset($attributeArray['rowspan']) && isset($attributeArray['colspan'])) {
//create merging rowspan and colspan
$columnTo = $column;
for ($i = 0; $i < $attributeArray['colspan'] - 1; $i++) {
++$columnTo;
}
$range = $column . $row . ':' . $columnTo . ($row + $attributeArray['rowspan'] - 1);
foreach (\PHPExcel_Cell::extractAllCellReferencesInRange($range) as $value) {
$this->rowspan[$value] = true;
}
$sheet->mergeCells($range);
$column = $columnTo;
} elseif (isset($attributeArray['rowspan'])) {
//create merging rowspan
$range = $column . $row . ':' . $column . ($row + $attributeArray['rowspan'] - 1);
foreach (\PHPExcel_Cell::extractAllCellReferencesInRange($range) as $value) {
$this->rowspan[$value] = true;
}
$sheet->mergeCells($range);
} elseif (isset($attributeArray['colspan'])) {
//create merging colspan
$columnTo = $column;
for ($i = 0; $i < $attributeArray['colspan'] - 1; $i++) {
++$columnTo;
}
$sheet->mergeCells($column . $row . ':' . $columnTo . $row);
$column = $columnTo;
}
++$column;
break;
case 'body':
$row = 1;
$column = 'A';
$content = '';
$this->tableLevel = 0;
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
break;
default:
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
}
}
}
}
/**
* Loads PHPExcel from file into PHPExcel instance
*
* @param string $pFilename
* @param PHPExcel $objPHPExcel
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
{
// Open file to validate
$this->openFile($pFilename);
if (!$this->isValidFormat()) {
fclose($this->fileHandle);
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid HTML file.");
}
// Close after validating
fclose($this->fileHandle);
// Create new PHPExcel
while ($objPHPExcel->getSheetCount() <= $this->sheetIndex) {
$objPHPExcel->createSheet();
}
$objPHPExcel->setActiveSheetIndex($this->sheetIndex);
// Create a new DOM object
$dom = new domDocument;
// Reload the HTML file into the DOM object
$loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanFile($pFilename), 'HTML-ENTITIES', 'UTF-8'));
if ($loaded === false) {
throw new PHPExcel_Reader_Exception('Failed to load ' . $pFilename . ' as a DOM Document');
}
// Discard white space
$dom->preserveWhiteSpace = false;
$row = 0;
$column = 'A';
$content = '';
$this->processDomElement($dom, $objPHPExcel->getActiveSheet(), $row, $column, $content);
// 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_HTML
*/
public function setSheetIndex($pValue = 0)
{
$this->sheetIndex = $pValue;
return $this;
}
/**
* Scan theXML for use of <!ENTITY to prevent XXE/XEE attacks
*
* @param string $xml
* @throws PHPExcel_Reader_Exception
*/
public function securityScan($xml)
{
$pattern = '/\\0?' . implode('\\0?', str_split('<!ENTITY')) . '\\0?/';
if (preg_match($pattern, $xml)) {
throw new PHPExcel_Reader_Exception('Detected use of ENTITY in XML, spreadsheet file load() aborted to prevent XXE/XEE attacks');
}
return $xml;
}
}

39
extend/PHPExcel/PHPExcel/Reader/IReadFilter.php

@ -0,0 +1,39 @@
<?php
/**
* PHPExcel_Reader_IReadFilter
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
interface PHPExcel_Reader_IReadFilter
{
/**
* Should this cell be read?
*
* @param $column Column address (as a string value like "A", or "IV")
* @param $row Row number
* @param $worksheetName Optional worksheet name
* @return boolean
*/
public function readCell($column, $row, $worksheetName = '');
}

46
extend/PHPExcel/PHPExcel/Reader/IReader.php

@ -0,0 +1,46 @@
<?php
/**
* PHPExcel_Reader_IReader
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
interface PHPExcel_Reader_IReader
{
/**
* Can the current PHPExcel_Reader_IReader read the file?
*
* @param string $pFilename
* @return boolean
*/
public function canRead($pFilename);
/**
* Loads PHPExcel from file
*
* @param string $pFilename
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function load($pFilename);
}

696
extend/PHPExcel/PHPExcel/Reader/OOCalc.php

@ -0,0 +1,696 @@
<?php
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
/**
* @ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel_Reader_OOCalc
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_OOCalc extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
{
/**
* Formats
*
* @var array
*/
private $styles = array();
/**
* Create a new PHPExcel_Reader_OOCalc
*/
public function __construct()
{
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter();
}
/**
* Can the current PHPExcel_Reader_IReader read the file?
*
* @param string $pFilename
* @return boolean
* @throws PHPExcel_Reader_Exception
*/
public function canRead($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$zipClass = PHPExcel_Settings::getZipClass();
// Check if zip class exists
// if (!class_exists($zipClass, false)) {
// throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled");
// }
$mimeType = 'UNKNOWN';
// Load file
$zip = new $zipClass;
if ($zip->open($pFilename) === true) {
// check if it is an OOXML archive
$stat = $zip->statName('mimetype');
if ($stat && ($stat['size'] <= 255)) {
$mimeType = $zip->getFromName($stat['name']);
} elseif ($stat = $zip->statName('META-INF/manifest.xml')) {
$xml = simplexml_load_string($this->securityScan($zip->getFromName('META-INF/manifest.xml')), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
$namespacesContent = $xml->getNamespaces(true);
if (isset($namespacesContent['manifest'])) {
$manifest = $xml->children($namespacesContent['manifest']);
foreach ($manifest as $manifestDataSet) {
$manifestAttributes = $manifestDataSet->attributes($namespacesContent['manifest']);
if ($manifestAttributes->{'full-path'} == '/') {
$mimeType = (string) $manifestAttributes->{'media-type'};
break;
}
}
}
}
$zip->close();
return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet');
}
return false;
}
/**
* Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetNames($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$zipClass = PHPExcel_Settings::getZipClass();
$zip = new $zipClass;
if (!$zip->open($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file.");
}
$worksheetNames = array();
$xml = new XMLReader();
$res = $xml->xml($this->securityScanFile('zip://'.realpath($pFilename).'#content.xml'), null, PHPExcel_Settings::getLibXmlLoaderOptions());
$xml->setParserProperty(2, true);
// Step into the first level of content of the XML
$xml->read();
while ($xml->read()) {
// Quickly jump through to the office:body node
while ($xml->name !== 'office:body') {
if ($xml->isEmptyElement) {
$xml->read();
} else {
$xml->next();
}
}
// Now read each node until we find our first table:table node
while ($xml->read()) {
if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) {
// Loop through each table:table node reading the table:name attribute for each worksheet name
do {
$worksheetNames[] = $xml->getAttribute('table:name');
$xml->next();
} while ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT);
}
}
}
return $worksheetNames;
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetInfo($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$worksheetInfo = array();
$zipClass = PHPExcel_Settings::getZipClass();
$zip = new $zipClass;
if (!$zip->open($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file.");
}
$xml = new XMLReader();
$res = $xml->xml($this->securityScanFile('zip://'.realpath($pFilename).'#content.xml'), null, PHPExcel_Settings::getLibXmlLoaderOptions());
$xml->setParserProperty(2, true);
// Step into the first level of content of the XML
$xml->read();
while ($xml->read()) {
// Quickly jump through to the office:body node
while ($xml->name !== 'office:body') {
if ($xml->isEmptyElement) {
$xml->read();
} else {
$xml->next();
}
}
// Now read each node until we find our first table:table node
while ($xml->read()) {
if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) {
$worksheetNames[] = $xml->getAttribute('table:name');
$tmpInfo = array(
'worksheetName' => $xml->getAttribute('table:name'),
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 0,
'totalColumns' => 0,
);
// Loop through each child node of the table:table element reading
$currCells = 0;
do {
$xml->read();
if ($xml->name == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) {
$rowspan = $xml->getAttribute('table:number-rows-repeated');
$rowspan = empty($rowspan) ? 1 : $rowspan;
$tmpInfo['totalRows'] += $rowspan;
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
$currCells = 0;
// Step into the row
$xml->read();
do {
if ($xml->name == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
if (!$xml->isEmptyElement) {
$currCells++;
$xml->next();
} else {
$xml->read();
}
} elseif ($xml->name == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) {
$mergeSize = $xml->getAttribute('table:number-columns-repeated');
$currCells += $mergeSize;
$xml->read();
}
} while ($xml->name != 'table:table-row');
}
} while ($xml->name != 'table:table');
$tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
$tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
$worksheetInfo[] = $tmpInfo;
}
}
// foreach ($workbookData->table as $worksheetDataSet) {
// $worksheetData = $worksheetDataSet->children($namespacesContent['table']);
// $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']);
//
// $rowIndex = 0;
// foreach ($worksheetData as $key => $rowData) {
// switch ($key) {
// case 'table-row' :
// $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']);
// $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ?
// $rowDataTableAttributes['number-rows-repeated'] : 1;
// $columnIndex = 0;
//
// foreach ($rowData as $key => $cellData) {
// $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']);
// $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ?
// $cellDataTableAttributes['number-columns-repeated'] : 1;
// $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']);
// if (isset($cellDataOfficeAttributes['value-type'])) {
// $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1);
// $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats);
// }
// $columnIndex += $colRepeats;
// }
// $rowIndex += $rowRepeats;
// break;
// }
// }
//
// $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
// $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1;
//
// }
// }
}
return $worksheetInfo;
}
/**
* Loads PHPExcel from file
*
* @param string $pFilename
* @return PHPExcel
* @throws PHPExcel_Reader_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
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$timezoneObj = new DateTimeZone('Europe/London');
$GMT = new DateTimeZone('UTC');
$zipClass = PHPExcel_Settings::getZipClass();
$zip = new $zipClass;
if (!$zip->open($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file.");
}
// echo '<h1>Meta Information</h1>';
$xml = simplexml_load_string($this->securityScan($zip->getFromName("meta.xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
$namespacesMeta = $xml->getNamespaces(true);
// echo '<pre>';
// print_r($namespacesMeta);
// echo '</pre><hr />';
$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) {
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'title':
$docProps->setTitle($propertyValue);
break;
case 'subject':
$docProps->setSubject($propertyValue);
break;
case 'creator':
$docProps->setCreator($propertyValue);
$docProps->setLastModifiedBy($propertyValue);
break;
case 'date':
$creationDate = strtotime($propertyValue);
$docProps->setCreated($creationDate);
$docProps->setModified($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']);
$propertyValue = (string) $propertyValue;
switch ($propertyName) {
case 'initial-creator':
$docProps->setCreator($propertyValue);
break;
case 'keyword':
$docProps->setKeywords($propertyValue);
break;
case 'creation-date':
$creationDate = strtotime($propertyValue);
$docProps->setCreated($creationDate);
break;
case 'user-defined':
$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING;
foreach ($propertyValueAttributes as $key => $value) {
if ($key == 'name') {
$propertyValueName = (string) $value;
} elseif ($key == 'value-type') {
switch ($value) {
case 'date':
$propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue, 'date');
$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE;
break;
case 'boolean':
$propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue, 'bool');
$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN;
break;
case 'float':
$propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue, 'r4');
$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT;
break;
default:
$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING;
}
}
}
$docProps->setCustomProperty($propertyValueName, $propertyValue, $propertyValueType);
break;
}
}
}
// echo '<h1>Workbook Content</h1>';
$xml = simplexml_load_string($this->securityScan($zip->getFromName("content.xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
$namespacesContent = $xml->getNamespaces(true);
// echo '<pre>';
// print_r($namespacesContent);
// echo '</pre><hr />';
$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 '<br />';
$worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']);
// print_r($worksheetDataAttributes);
// echo '<br />';
if ((isset($this->loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) &&
(!in_array($worksheetDataAttributes['name'], $this->loadSheetsOnly))) {
continue;
}
// echo '<h2>Worksheet '.$worksheetDataAttributes['name'].'</h2>';
// Create new Worksheet
$objPHPExcel->createSheet();
$objPHPExcel->setActiveSheetIndex($worksheetID);
if (isset($worksheetDataAttributes['name'])) {
$worksheetName = (string) $worksheetDataAttributes['name'];
// Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in
// formula cells... during the load, all formulae should be correct, and we're simply
// bringing the worksheet name in line with the formula, not the reverse
$objPHPExcel->getActiveSheet()->setTitle($worksheetName, false);
}
$rowID = 1;
foreach ($worksheetData as $key => $rowData) {
// echo '<b>'.$key.'</b><br />';
switch ($key) {
case 'table-header-rows':
foreach ($rowData as $key => $cellData) {
$rowData = $cellData;
break;
}
case 'table-row':
$rowDataTableAttributes = $rowData->attributes($namespacesContent['table']);
$rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? $rowDataTableAttributes['number-rows-repeated'] : 1;
$columnID = 'A';
foreach ($rowData as $key => $cellData) {
if ($this->getReadFilter() !== null) {
if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) {
continue;
}
}
// echo '<b>'.$columnID.$rowID.'</b><br />';
$cellDataText = (isset($namespacesContent['text'])) ? $cellData->children($namespacesContent['text']) : '';
$cellDataOffice = $cellData->children($namespacesContent['office']);
$cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']);
$cellDataTableAttributes = $cellData->attributes($namespacesContent['table']);
// echo 'Office Attributes: ';
// print_r($cellDataOfficeAttributes);
// echo '<br />Table Attributes: ';
// print_r($cellDataTableAttributes);
// echo '<br />Cell Data Text';
// print_r($cellDataText);
// echo '<br />';
//
$type = $formatting = $hyperlink = null;
$hasCalculatedValue = false;
$cellDataFormula = '';
if (isset($cellDataTableAttributes['formula'])) {
$cellDataFormula = $cellDataTableAttributes['formula'];
$hasCalculatedValue = true;
}
if (isset($cellDataOffice->annotation)) {
// echo 'Cell has comment<br />';
$annotationText = $cellDataOffice->annotation->children($namespacesContent['text']);
$textArray = array();
foreach ($annotationText as $t) {
if (isset($t->span)) {
foreach ($t->span as $text) {
$textArray[] = (string)$text;
}
} else {
$textArray[] = (string) $t;
}
}
$text = implode("\n", $textArray);
// echo $text, '<br />';
$objPHPExcel->getActiveSheet()->getComment($columnID.$rowID)->setText($this->parseRichText($text));
// ->setAuthor( $author )
}
if (isset($cellDataText->p)) {
// Consolidate if there are multiple p records (maybe with spans as well)
$dataArray = array();
// Text can have multiple text:p and within those, multiple text:span.
// text:p newlines, but text:span does not.
// Also, here we assume there is no text data is span fields are specified, since
// we have no way of knowing proper positioning anyway.
foreach ($cellDataText->p as $pData) {
if (isset($pData->span)) {
// span sections do not newline, so we just create one large string here
$spanSection = "";
foreach ($pData->span as $spanData) {
$spanSection .= $spanData;
}
array_push($dataArray, $spanSection);
} else {
array_push($dataArray, $pData);
}
}
$allCellDataText = implode($dataArray, "\n");
// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'<br />';
switch ($cellDataOfficeAttributes['value-type']) {
case 'string':
$type = PHPExcel_Cell_DataType::TYPE_STRING;
$dataValue = $allCellDataText;
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 = ($allCellDataText == 'TRUE') ? true : false;
break;
case 'percentage':
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
$dataValue = (float) $cellDataOfficeAttributes['value'];
if (floor($dataValue) == $dataValue) {
$dataValue = (integer) $dataValue;
}
$formatting = PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00;
break;
case 'currency':
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
$dataValue = (float) $cellDataOfficeAttributes['value'];
if (floor($dataValue) == $dataValue) {
$dataValue = (integer) $dataValue;
}
$formatting = PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE;
break;
case 'float':
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
$dataValue = (float) $cellDataOfficeAttributes['value'];
if (floor($dataValue) == $dataValue) {
if ($dataValue == (integer) $dataValue) {
$dataValue = (integer) $dataValue;
} else {
$dataValue = (float) $dataValue;
}
}
break;
case 'date':
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
$dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT);
$dateObj->setTimeZone($timezoneObj);
list($year, $month, $day, $hour, $minute, $second) = explode(' ', $dateObj->format('Y m d H i s'));
$dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year, $month, $day, $hour, $minute, $second);
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.'<br />';
// if ($hyperlink !== null) {
// echo 'Hyperlink is '.$hyperlink.'<br />';
// }
} else {
$type = PHPExcel_Cell_DataType::TYPE_NULL;
$dataValue = null;
}
if ($hasCalculatedValue) {
$type = PHPExcel_Cell_DataType::TYPE_FORMULA;
// echo 'Formula: ', $cellDataFormula, PHP_EOL;
$cellDataFormula = substr($cellDataFormula, strpos($cellDataFormula, ':=')+1);
$temp = explode('"', $cellDataFormula);
$tKey = false;
foreach ($temp as &$value) {
// Only replace in alternate array entries (i.e. non-quoted blocks)
if ($tKey = !$tKey) {
$value = preg_replace('/\[([^\.]+)\.([^\.]+):\.([^\.]+)\]/Ui', '$1!$2:$3', $value); // Cell range reference in another sheet
$value = preg_replace('/\[([^\.]+)\.([^\.]+)\]/Ui', '$1!$2', $value); // Cell reference in another sheet
$value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/Ui', '$1:$2', $value); // Cell range reference
$value = preg_replace('/\[\.([^\.]+)\]/Ui', '$1', $value); // Simple cell reference
$value = PHPExcel_Calculation::translateSeparator(';', ',', $value, $inBraces);
}
}
unset($value);
// Then rebuild the formula string
$cellDataFormula = implode('"', $temp);
// echo 'Adjusted Formula: ', $cellDataFormula, PHP_EOL;
}
$colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? $cellDataTableAttributes['number-columns-repeated'] : 1;
if ($type !== null) {
for ($i = 0; $i < $colRepeats; ++$i) {
if ($i > 0) {
++$columnID;
}
if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) {
for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) {
$rID = $rowID + $rowAdjust;
$objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue), $type);
if ($hasCalculatedValue) {
// echo 'Forumla result is '.$dataValue.'<br />';
$objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue);
}
if ($formatting !== null) {
$objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting);
} else {
$objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL);
}
if ($hyperlink !== null) {
$objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink);
}
}
}
}
}
// Merged cells
if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) {
if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->readDataOnly)) {
$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);
}
}
++$columnID;
}
$rowID += $rowRepeats;
break;
}
}
++$worksheetID;
}
}
// Return
return $objPHPExcel;
}
private function parseRichText($is = '')
{
$value = new PHPExcel_RichText();
$value->createText($is);
return $value;
}
}

478
extend/PHPExcel/PHPExcel/Reader/SYLK.php

@ -0,0 +1,478 @@
<?php
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
/**
* @ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel_Reader_SYLK
*
* Copyright (c) 2006 - 2015 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_Reader
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Reader_SYLK extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
{
/**
* Input encoding
*
* @var string
*/
private $inputEncoding = 'ANSI';
/**
* Sheet index to read
*
* @var int
*/
private $sheetIndex = 0;
/**
* Formats
*
* @var array
*/
private $formats = array();
/**
* Format Count
*
* @var int
*/
private $format = 0;
/**
* Create a new PHPExcel_Reader_SYLK
*/
public function __construct()
{
$this->readFilter = new PHPExcel_Reader_DefaultReadFilter();
}
/**
* Validate that the current file is a SYLK file
*
* @return boolean
*/
protected function isValidFormat()
{
// Read sample data (first 2 KB will do)
$data = fread($this->fileHandle, 2048);
// 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;
}
/**
* Set input encoding
*
* @param string $pValue Input encoding
*/
public function setInputEncoding($pValue = 'ANSI')
{
$this->inputEncoding = $pValue;
return $this;
}
/**
* Get input encoding
*
* @return string
*/
public function getInputEncoding()
{
return $this->inputEncoding;
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetInfo($pFilename)
{
// Open file
$this->openFile($pFilename);
if (!$this->isValidFormat()) {
fclose($this->fileHandle);
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file.");
}
$fileHandle = $this->fileHandle;
rewind($fileHandle);
$worksheetInfo = array();
$worksheetInfo[0]['worksheetName'] = 'Worksheet';
$worksheetInfo[0]['lastColumnLetter'] = 'A';
$worksheetInfo[0]['lastColumnIndex'] = 0;
$worksheetInfo[0]['totalRows'] = 0;
$worksheetInfo[0]['totalColumns'] = 0;
// Loop through file
$rowData = array();
// loop through one row (line) at a time in the file
$rowIndex = 0;
while (($rowData = fgets($fileHandle)) !== false) {
$columnIndex = 0;
// convert SYLK encoded $rowData to UTF-8
$rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData);
// explode each row at semicolons while taking into account that literal semicolon (;)
// is escaped like this (;;)
$rowData = explode("\t", str_replace('¤', ';', str_replace(';', "\t", str_replace(';;', '¤', rtrim($rowData)))));
$dataType = array_shift($rowData);
if ($dataType == 'C') {
// Read cell value data
foreach ($rowData as $rowDatum) {
switch ($rowDatum{0}) {
case 'C':
case 'X':
$columnIndex = substr($rowDatum, 1) - 1;
break;
case 'R':
case 'Y':
$rowIndex = substr($rowDatum, 1);
break;
}
$worksheetInfo[0]['totalRows'] = max($worksheetInfo[0]['totalRows'], $rowIndex);
$worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], $columnIndex);
}
}
}
$worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']);
$worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1;
// Close file
fclose($fileHandle);
return $worksheetInfo;
}
/**
* Loads PHPExcel from file
*
* @param string $pFilename
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function load($pFilename)
{
// Create new PHPExcel
$objPHPExcel = new PHPExcel();
// Load into this instance
return $this->loadIntoExisting($pFilename, $objPHPExcel);
}
/**
* Loads PHPExcel from file into PHPExcel instance
*
* @param string $pFilename
* @param PHPExcel $objPHPExcel
* @return PHPExcel
* @throws PHPExcel_Reader_Exception
*/
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
{
// Open file
$this->openFile($pFilename);
if (!$this->isValidFormat()) {
fclose($this->fileHandle);
throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file.");
}
$fileHandle = $this->fileHandle;
rewind($fileHandle);
// Create new PHPExcel
while ($objPHPExcel->getSheetCount() <= $this->sheetIndex) {
$objPHPExcel->createSheet();
}
$objPHPExcel->setActiveSheetIndex($this->sheetIndex);
$fromFormats = array('\-', '\ ');
$toFormats = array('-', ' ');
// Loop through file
$rowData = array();
$column = $row = '';
// loop through one row (line) at a time in the file
while (($rowData = fgets($fileHandle)) !== false) {
// convert SYLK encoded $rowData to UTF-8
$rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData);
// explode each row at semicolons while taking into account that literal semicolon (;)
// is escaped like this (;;)
$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<strlen($styleSettings); ++$i) {
switch ($styleSettings{$i}) {
case 'I':
$formatArray['font']['italic'] = true;
break;
case 'D':
$formatArray['font']['bold'] = true;
break;
case 'T':
$formatArray['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
case 'B':
$formatArray['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
case 'L':
$formatArray['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
case 'R':
$formatArray['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
}
}
break;
}
}
$this->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);
$key = false;
foreach ($temp as &$value) {
// Only count/replace in alternate array entries
if ($key = !$key) {
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()->getCell($columnLetter.$row)->setValue(($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<strlen($styleSettings); ++$i) {
switch ($styleSettings{$i}) {
case 'I':
$styleData['font']['italic'] = true;
break;
case 'D':
$styleData['font']['bold'] = true;
break;
case 'T':
$styleData['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
case 'B':
$styleData['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
case 'L':
$styleData['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
case 'R':
$styleData['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN;
break;
}
}
break;
}
}
if (($formatStyle > '') && ($column > '') && ($row > '')) {
$columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1);
if (isset($this->formats[$formatStyle])) {
$objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->formats[$formatStyle]);
}
}
if ((!empty($styleData)) && ($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 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;
}
}

156
extend/PHPExcel/PHPExcel/Shared/CodePage.php

@ -0,0 +1,156 @@
<?php
/**
* PHPExcel_Shared_CodePage
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_CodePage
{
/**
* Convert Microsoft Code Page Identifier to Code Page Name which iconv
* and mbstring understands
*
* @param integer $codePage Microsoft Code Page Indentifier
* @return string Code Page Name
* @throws PHPExcel_Exception
*/
public static function NumberToName($codePage = 1252)
{
switch ($codePage) {
case 367:
return 'ASCII'; // ASCII
case 437:
return 'CP437'; // OEM US
case 720:
throw new PHPExcel_Exception('Code page 720 not supported.'); // OEM Arabic
case 737:
return 'CP737'; // OEM Greek
case 775:
return 'CP775'; // OEM Baltic
case 850:
return 'CP850'; // OEM Latin I
case 852:
return 'CP852'; // OEM Latin II (Central European)
case 855:
return 'CP855'; // OEM Cyrillic
case 857:
return 'CP857'; // OEM Turkish
case 858:
return 'CP858'; // OEM Multilingual Latin I with Euro
case 860:
return 'CP860'; // OEM Portugese
case 861:
return 'CP861'; // OEM Icelandic
case 862:
return 'CP862'; // OEM Hebrew
case 863:
return 'CP863'; // OEM Canadian (French)
case 864:
return 'CP864'; // OEM Arabic
case 865:
return 'CP865'; // OEM Nordic
case 866:
return 'CP866'; // OEM Cyrillic (Russian)
case 869:
return 'CP869'; // OEM Greek (Modern)
case 874:
return 'CP874'; // ANSI Thai
case 932:
return 'CP932'; // ANSI Japanese Shift-JIS
case 936:
return 'CP936'; // ANSI Chinese Simplified GBK
case 949:
return 'CP949'; // ANSI Korean (Wansung)
case 950:
return 'CP950'; // ANSI Chinese Traditional BIG5
case 1200:
return 'UTF-16LE'; // UTF-16 (BIFF8)
case 1250:
return 'CP1250'; // ANSI Latin II (Central European)
case 1251:
return 'CP1251'; // ANSI Cyrillic
case 0:
// CodePage is not always correctly set when the xls file was saved by Apple's Numbers program
case 1252:
return 'CP1252'; // ANSI Latin I (BIFF4-BIFF7)
case 1253:
return 'CP1253'; // ANSI Greek
case 1254:
return 'CP1254'; // ANSI Turkish
case 1255:
return 'CP1255'; // ANSI Hebrew
case 1256:
return 'CP1256'; // ANSI Arabic
case 1257:
return 'CP1257'; // ANSI Baltic
case 1258:
return 'CP1258'; // ANSI Vietnamese
case 1361:
return 'CP1361'; // ANSI Korean (Johab)
case 10000:
return 'MAC'; // Apple Roman
case 10001:
return 'CP932'; // Macintosh Japanese
case 10002:
return 'CP950'; // Macintosh Chinese Traditional
case 10003:
return 'CP1361'; // Macintosh Korean
case 10004:
return 'MACARABIC'; // Apple Arabic
case 10005:
return 'MACHEBREW'; // Apple Hebrew
case 10006:
return 'MACGREEK'; // Macintosh Greek
case 10007:
return 'MACCYRILLIC'; // Macintosh Cyrillic
case 10008:
return 'CP936'; // Macintosh - Simplified Chinese (GB 2312)
case 10010:
return 'MACROMANIA'; // Macintosh Romania
case 10017:
return 'MACUKRAINE'; // Macintosh Ukraine
case 10021:
return 'MACTHAI'; // Macintosh Thai
case 10029:
return 'MACCENTRALEUROPE'; // Macintosh Central Europe
case 10079:
return 'MACICELAND'; // Macintosh Icelandic
case 10081:
return 'MACTURKISH'; // Macintosh Turkish
case 10082:
return 'MACCROATIAN'; // Macintosh Croatian
case 21010:
return 'UTF-16LE'; // UTF-16 (BIFF8) This isn't correct, but some Excel writer libraries erroneously use Codepage 21010 for UTF-16LE
case 32768:
return 'MAC'; // Apple Roman
case 32769:
throw new PHPExcel_Exception('Code page 32769 not supported.'); // ANSI Latin I (BIFF2-BIFF3)
case 65000:
return 'UTF-7'; // Unicode (UTF-7)
case 65001:
return 'UTF-8'; // Unicode (UTF-8)
}
throw new PHPExcel_Exception('Unknown codepage: ' . $codePage);
}
}

418
extend/PHPExcel/PHPExcel/Shared/Date.php

@ -0,0 +1,418 @@
<?php
/**
* PHPExcel_Shared_Date
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Date
{
/** constants */
const CALENDAR_WINDOWS_1900 = 1900; // Base date of 1st Jan 1900 = 1.0
const CALENDAR_MAC_1904 = 1904; // Base date of 2nd Jan 1904 = 1.0
/*
* Names of the months of the year, indexed by shortname
* Planned usage for locale settings
*
* @public
* @var string[]
*/
public static $monthNames = array(
'Jan' => 'January',
'Feb' => 'February',
'Mar' => 'March',
'Apr' => 'April',
'May' => 'May',
'Jun' => 'June',
'Jul' => 'July',
'Aug' => 'August',
'Sep' => 'September',
'Oct' => 'October',
'Nov' => 'November',
'Dec' => 'December',
);
/*
* Names of the months of the year, indexed by shortname
* Planned usage for locale settings
*
* @public
* @var string[]
*/
public static $numberSuffixes = array(
'st',
'nd',
'rd',
'th',
);
/*
* Base calendar year to use for calculations
*
* @private
* @var int
*/
protected static $excelBaseDate = self::CALENDAR_WINDOWS_1900;
/**
* Set the Excel calendar (Windows 1900 or Mac 1904)
*
* @param integer $baseDate Excel base date (1900 or 1904)
* @return boolean Success or failure
*/
public static function setExcelCalendar($baseDate)
{
if (($baseDate == self::CALENDAR_WINDOWS_1900) ||
($baseDate == self::CALENDAR_MAC_1904)) {
self::$excelBaseDate = $baseDate;
return true;
}
return false;
}
/**
* Return the Excel calendar (Windows 1900 or Mac 1904)
*
* @return integer Excel base date (1900 or 1904)
*/
public static function getExcelCalendar()
{
return self::$excelBaseDate;
}
/**
* Convert a date from Excel to PHP
*
* @param integer $dateValue Excel date/time value
* @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as
* a UST timestamp, or adjusted to UST
* @param string $timezone The timezone for finding the adjustment from UST
* @return integer PHP serialized date/time
*/
public static function ExcelToPHP($dateValue = 0, $adjustToTimezone = false, $timezone = null)
{
if (self::$excelBaseDate == self::CALENDAR_WINDOWS_1900) {
$myexcelBaseDate = 25569;
// Adjust for the spurious 29-Feb-1900 (Day 60)
if ($dateValue < 60) {
--$myexcelBaseDate;
}
} else {
$myexcelBaseDate = 24107;
}
// Perform conversion
if ($dateValue >= 1) {
$utcDays = $dateValue - $myexcelBaseDate;
$returnValue = round($utcDays * 86400);
if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) {
$returnValue = (integer) $returnValue;
}
} else {
$hours = round($dateValue * 24);
$mins = round($dateValue * 1440) - round($hours * 60);
$secs = round($dateValue * 86400) - round($hours * 3600) - round($mins * 60);
$returnValue = (integer) gmmktime($hours, $mins, $secs);
}
$timezoneAdjustment = ($adjustToTimezone) ?
PHPExcel_Shared_TimeZone::getTimezoneAdjustment($timezone, $returnValue) :
0;
return $returnValue + $timezoneAdjustment;
}
/**
* Convert a date from Excel to a PHP Date/Time object
*
* @param integer $dateValue Excel date/time value
* @return DateTime PHP date/time object
*/
public static function ExcelToPHPObject($dateValue = 0)
{
$dateTime = self::ExcelToPHP($dateValue);
$days = floor($dateTime / 86400);
$time = round((($dateTime / 86400) - $days) * 86400);
$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;
}
/**
* Convert a date from PHP to Excel
*
* @param mixed $dateValue PHP serialized date/time or date object
* @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as
* a UST timestamp, or adjusted to UST
* @param string $timezone The timezone for finding the adjustment from UST
* @return mixed Excel date/time value
* or boolean FALSE on failure
*/
public static function PHPToExcel($dateValue = 0, $adjustToTimezone = false, $timezone = null)
{
$saveTimeZone = date_default_timezone_get();
date_default_timezone_set('UTC');
$timezoneAdjustment = ($adjustToTimezone) ?
PHPExcel_Shared_TimeZone::getTimezoneAdjustment($timezone ? $timezone : $saveTimeZone, $dateValue) :
0;
$retValue = false;
if ((is_object($dateValue)) && ($dateValue instanceof DateTime)) {
$dateValue->add(new DateInterval('PT' . $timezoneAdjustment . 'S'));
$retValue = self::FormattedPHPToExcel($dateValue->format('Y'), $dateValue->format('m'), $dateValue->format('d'), $dateValue->format('H'), $dateValue->format('i'), $dateValue->format('s'));
} elseif (is_numeric($dateValue)) {
$dateValue += $timezoneAdjustment;
$retValue = self::FormattedPHPToExcel(date('Y', $dateValue), date('m', $dateValue), date('d', $dateValue), date('H', $dateValue), date('i', $dateValue), date('s', $dateValue));
} elseif (is_string($dateValue)) {
$retValue = self::stringToExcel($dateValue);
}
date_default_timezone_set($saveTimeZone);
return $retValue;
}
/**
* FormattedPHPToExcel
*
* @param integer $year
* @param integer $month
* @param integer $day
* @param integer $hours
* @param integer $minutes
* @param integer $seconds
* @return integer Excel date/time value
*/
public static function FormattedPHPToExcel($year, $month, $day, $hours = 0, $minutes = 0, $seconds = 0)
{
if (self::$excelBaseDate == self::CALENDAR_WINDOWS_1900) {
//
// Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel
// This affects every date following 28th February 1900
//
$excel1900isLeapYear = true;
if (($year == 1900) && ($month <= 2)) {
$excel1900isLeapYear = false;
}
$myexcelBaseDate = 2415020;
} else {
$myexcelBaseDate = 2416481;
$excel1900isLeapYear = false;
}
// Julian base date Adjustment
if ($month > 2) {
$month -= 3;
} else {
$month += 9;
--$year;
}
// Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0)
$century = substr($year, 0, 2);
$decade = substr($year, 2, 2);
$excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $myexcelBaseDate + $excel1900isLeapYear;
$excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400;
return (float) $excelDate + $excelTime;
}
/**
* Is a given cell a date/time?
*
* @param PHPExcel_Cell $pCell
* @return boolean
*/
public static function isDateTime(PHPExcel_Cell $pCell)
{
return self::isDateTimeFormat(
$pCell->getWorksheet()->getStyle(
$pCell->getCoordinate()
)->getNumberFormat()
);
}
/**
* Is a given number format a date/time?
*
* @param PHPExcel_Style_NumberFormat $pFormat
* @return boolean
*/
public static function isDateTimeFormat(PHPExcel_Style_NumberFormat $pFormat)
{
return self::isDateTimeFormatCode($pFormat->getFormatCode());
}
private static $possibleDateFormatCharacters = 'eymdHs';
/**
* Is a given number format code a date/time?
*
* @param string $pFormatCode
* @return boolean
*/
public static function isDateTimeFormatCode($pFormatCode = '')
{
if (strtolower($pFormatCode) === strtolower(PHPExcel_Style_NumberFormat::FORMAT_GENERAL)) {
// "General" contains an epoch letter 'e', so we trap for it explicitly here (case-insensitive check)
return false;
}
if (preg_match('/[0#]E[+-]0/i', $pFormatCode)) {
// Scientific format
return false;
}
// Switch on formatcode
switch ($pFormatCode) {
// Explicitly defined date formats
case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYSLASH:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYMINUS:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMMINUS:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_MYMINUS:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DATETIME:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME1:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME2:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME5:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME6:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME7:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME8:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDDSLASH:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX16:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX17:
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX22:
return true;
}
// Typically number, currency or accounting (or occasionally fraction) formats
if ((substr($pFormatCode, 0, 1) == '_') || (substr($pFormatCode, 0, 2) == '0 ')) {
return false;
}
// Try checking for any of the date formatting characters that don't appear within square braces
if (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i', $pFormatCode)) {
// We might also have a format mask containing quoted strings...
// we don't want to test for any of our characters within the quoted blocks
if (strpos($pFormatCode, '"') !== false) {
$segMatcher = false;
foreach (explode('"', $pFormatCode) as $subVal) {
// Only test in alternate array entries (the non-quoted blocks)
if (($segMatcher = !$segMatcher) &&
(preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i', $subVal))) {
return true;
}
}
return false;
}
return true;
}
// No date...
return false;
}
/**
* Convert a date/time string to Excel time
*
* @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10'
* @return float|FALSE Excel date/time serial value
*/
public static function stringToExcel($dateValue = '')
{
if (strlen($dateValue) < 2) {
return false;
}
if (!preg_match('/^(\d{1,4}[ \.\/\-][A-Z]{3,9}([ \.\/\-]\d{1,4})?|[A-Z]{3,9}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?|\d{1,4}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?)( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/iu', $dateValue)) {
return false;
}
$dateValueNew = PHPExcel_Calculation_DateTime::DATEVALUE($dateValue);
if ($dateValueNew === PHPExcel_Calculation_Functions::VALUE()) {
return false;
}
if (strpos($dateValue, ':') !== false) {
$timeValue = PHPExcel_Calculation_DateTime::TIMEVALUE($dateValue);
if ($timeValue === PHPExcel_Calculation_Functions::VALUE()) {
return false;
}
$dateValueNew += $timeValue;
}
return $dateValueNew;
}
/**
* Converts a month name (either a long or a short name) to a month number
*
* @param string $month Month name or abbreviation
* @return integer|string Month number (1 - 12), or the original string argument if it isn't a valid month name
*/
public static function monthStringToNumber($month)
{
$monthIndex = 1;
foreach (self::$monthNames as $shortMonthName => $longMonthName) {
if (($month === $longMonthName) || ($month === $shortMonthName)) {
return $monthIndex;
}
++$monthIndex;
}
return $month;
}
/**
* Strips an ordinal froma numeric value
*
* @param string $day Day number with an ordinal
* @return integer|string The integer value with any ordinal stripped, or the original string argument if it isn't a valid numeric
*/
public static function dayStringToNumber($day)
{
$strippedDayValue = (str_replace(self::$numberSuffixes, '', $day));
if (is_numeric($strippedDayValue)) {
return (integer) $strippedDayValue;
}
return $day;
}
}

270
extend/PHPExcel/PHPExcel/Shared/Drawing.php

@ -0,0 +1,270 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Shared_Drawing
*
* @category PHPExcel
* @package PHPExcel_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Shared_Drawing
{
/**
* Convert pixels to EMU
*
* @param int $pValue Value in pixels
* @return int Value in EMU
*/
public static function pixelsToEMU($pValue = 0)
{
return round($pValue * 9525);
}
/**
* Convert EMU to pixels
*
* @param int $pValue Value in EMU
* @return int Value in pixels
*/
public static function EMUToPixels($pValue = 0)
{
if ($pValue != 0) {
return round($pValue / 9525);
} else {
return 0;
}
}
/**
* 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 PHPExcel_Style_Font $pDefaultFont Default font of the workbook
* @return int Value in cell dimension
*/
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 {
// 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
*
* @param int $pValue Value in pixels
* @return int Value in points
*/
public static function pixelsToPoints($pValue = 0)
{
return $pValue * 0.67777777;
}
/**
* Convert points to pixels
*
* @param int $pValue Value in points
* @return int Value in pixels
*/
public static function pointsToPixels($pValue = 0)
{
if ($pValue != 0) {
return (int) ceil($pValue * 1.333333333);
} else {
return 0;
}
}
/**
* Convert degrees to angle
*
* @param int $pValue Degrees
* @return int Angle
*/
public static function degreesToAngle($pValue = 0)
{
return (int)round($pValue * 60000);
}
/**
* Convert angle to degrees
*
* @param int $pValue Angle
* @return int Degrees
*/
public static function angleToDegrees($pValue = 0)
{
if ($pValue != 0) {
return round($pValue / 60000);
} else {
return 0;
}
}
/**
* Create a new image from file. By alexander at alexauto dot nl
*
* @link http://www.php.net/manual/en/function.imagecreatefromwbmp.php#86214
* @param string $filename Path to Windows DIB (BMP) image
* @return resource
*/
public static function imagecreatefrombmp($p_sFile)
{
// Load the image into a string
$file = fopen($p_sFile, "rb");
$read = fread($file, 10);
while (!feof($file) && ($read<>"")) {
$read .= fread($file, 1024);
}
$temp = unpack("H*", $read);
$hex = $temp[1];
$header = substr($hex, 0, 108);
// Process the header
// Structure: http://www.fastgraph.com/help/bmp_header_format.html
if (substr($header, 0, 4)=="424d") {
// Cut it in parts of 2 bytes
$header_parts = str_split($header, 2);
// Get the width 4 bytes
$width = hexdec($header_parts[19].$header_parts[18]);
// Get the height 4 bytes
$height = hexdec($header_parts[23].$header_parts[22]);
// Unset the header params
unset($header_parts);
}
// Define starting X and Y
$x = 0;
$y = 1;
// Create newimage
$image = imagecreatetruecolor($width, $height);
// Grab the body from the image
$body = substr($hex, 108);
// Calculate if padding at the end-line is needed
// Divided by two to keep overview.
// 1 byte = 2 HEX-chars
$body_size = (strlen($body)/2);
$header_size = ($width*$height);
// Use end-line padding? Only when needed
$usePadding = ($body_size>($header_size*3)+4);
// Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption
// Calculate the next DWORD-position in the body
for ($i = 0; $i < $body_size; $i += 3) {
// Calculate line-ending and padding
if ($x >= $width) {
// If padding needed, ignore image-padding
// Shift i to the ending of the current 32-bit-block
if ($usePadding) {
$i += $width%4;
}
// Reset horizontal position
$x = 0;
// Raise the height-position (bottom-up)
$y++;
// Reached the image-height? Break the for-loop
if ($y > $height) {
break;
}
}
// Calculation of the RGB-pixel (defined as BGR in image-data)
// Define $i_pos as absolute position in the body
$i_pos = $i * 2;
$r = hexdec($body[$i_pos+4].$body[$i_pos+5]);
$g = hexdec($body[$i_pos+2].$body[$i_pos+3]);
$b = hexdec($body[$i_pos].$body[$i_pos+1]);
// Calculate and draw the pixel
$color = imagecolorallocate($image, $r, $g, $b);
imagesetpixel($image, $x, $height-$y, $color);
// Raise the horizontal position
$x++;
}
// Unset the body / free the memory
unset($body);
// Return image-object
return $image;
}
}

83
extend/PHPExcel/PHPExcel/Shared/Escher.php

@ -0,0 +1,83 @@
<?php
/**
* PHPExcel_Shared_Escher
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher
{
/**
* Drawing Group Container
*
* @var PHPExcel_Shared_Escher_DggContainer
*/
private $dggContainer;
/**
* Drawing Container
*
* @var PHPExcel_Shared_Escher_DgContainer
*/
private $dgContainer;
/**
* Get Drawing Group Container
*
* @return PHPExcel_Shared_Escher_DgContainer
*/
public function getDggContainer()
{
return $this->dggContainer;
}
/**
* Set Drawing Group Container
*
* @param PHPExcel_Shared_Escher_DggContainer $dggContainer
*/
public function setDggContainer($dggContainer)
{
return $this->dggContainer = $dggContainer;
}
/**
* Get Drawing Container
*
* @return PHPExcel_Shared_Escher_DgContainer
*/
public function getDgContainer()
{
return $this->dgContainer;
}
/**
* Set Drawing Container
*
* @param PHPExcel_Shared_Escher_DgContainer $dgContainer
*/
public function setDgContainer($dgContainer)
{
return $this->dgContainer = $dgContainer;
}
}

75
extend/PHPExcel/PHPExcel/Shared/Escher/DgContainer.php

@ -0,0 +1,75 @@
<?php
/**
* PHPExcel_Shared_Escher_DgContainer
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher_DgContainer
{
/**
* Drawing index, 1-based.
*
* @var int
*/
private $dgId;
/**
* Last shape index in this drawing
*
* @var int
*/
private $lastSpId;
private $spgrContainer = null;
public function getDgId()
{
return $this->dgId;
}
public function setDgId($value)
{
$this->dgId = $value;
}
public function getLastSpId()
{
return $this->lastSpId;
}
public function setLastSpId($value)
{
$this->lastSpId = $value;
}
public function getSpgrContainer()
{
return $this->spgrContainer;
}
public function setSpgrContainer($spgrContainer)
{
return $this->spgrContainer = $spgrContainer;
}
}

102
extend/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php

@ -0,0 +1,102 @@
<?php
/**
* PHPExcel_Shared_Escher_DgContainer_SpgrContainer
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher_DgContainer_SpgrContainer
{
/**
* Parent Shape Group Container
*
* @var PHPExcel_Shared_Escher_DgContainer_SpgrContainer
*/
private $parent;
/**
* Shape Container collection
*
* @var array
*/
private $children = array();
/**
* Set parent Shape Group Container
*
* @param PHPExcel_Shared_Escher_DgContainer_SpgrContainer $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* Get the parent Shape Group Container if any
*
* @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer|null
*/
public function getParent()
{
return $this->parent;
}
/**
* Add a child. This will be either spgrContainer or spContainer
*
* @param mixed $child
*/
public function addChild($child)
{
$this->children[] = $child;
$child->setParent($this);
}
/**
* Get collection of Shape Containers
*/
public function getChildren()
{
return $this->children;
}
/**
* Recursively get all spContainers within this spgrContainer
*
* @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer[]
*/
public function getAllSpContainers()
{
$allSpContainers = array();
foreach ($this->children as $child) {
if ($child instanceof PHPExcel_Shared_Escher_DgContainer_SpgrContainer) {
$allSpContainers = array_merge($allSpContainers, $child->getAllSpContainers());
} else {
$allSpContainers[] = $child;
}
}
return $allSpContainers;
}
}

388
extend/PHPExcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php

@ -0,0 +1,388 @@
<?php
/**
* PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer
{
/**
* Parent Shape Group Container
*
* @var PHPExcel_Shared_Escher_DgContainer_SpgrContainer
*/
private $parent;
/**
* Is this a group shape?
*
* @var boolean
*/
private $spgr = false;
/**
* Shape type
*
* @var int
*/
private $spType;
/**
* Shape flag
*
* @var int
*/
private $spFlag;
/**
* Shape index (usually group shape has index 0, and the rest: 1,2,3...)
*
* @var boolean
*/
private $spId;
/**
* Array of options
*
* @var array
*/
private $OPT;
/**
* Cell coordinates of upper-left corner of shape, e.g. 'A1'
*
* @var string
*/
private $startCoordinates;
/**
* Horizontal offset of upper-left corner of shape measured in 1/1024 of column width
*
* @var int
*/
private $startOffsetX;
/**
* Vertical offset of upper-left corner of shape measured in 1/256 of row height
*
* @var int
*/
private $startOffsetY;
/**
* Cell coordinates of bottom-right corner of shape, e.g. 'B2'
*
* @var string
*/
private $endCoordinates;
/**
* Horizontal offset of bottom-right corner of shape measured in 1/1024 of column width
*
* @var int
*/
private $endOffsetX;
/**
* Vertical offset of bottom-right corner of shape measured in 1/256 of row height
*
* @var int
*/
private $endOffsetY;
/**
* Set parent Shape Group Container
*
* @param PHPExcel_Shared_Escher_DgContainer_SpgrContainer $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* Get the parent Shape Group Container
*
* @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer
*/
public function getParent()
{
return $this->parent;
}
/**
* Set whether this is a group shape
*
* @param boolean $value
*/
public function setSpgr($value = false)
{
$this->spgr = $value;
}
/**
* Get whether this is a group shape
*
* @return boolean
*/
public function getSpgr()
{
return $this->spgr;
}
/**
* Set the shape type
*
* @param int $value
*/
public function setSpType($value)
{
$this->spType = $value;
}
/**
* Get the shape type
*
* @return int
*/
public function getSpType()
{
return $this->spType;
}
/**
* Set the shape flag
*
* @param int $value
*/
public function setSpFlag($value)
{
$this->spFlag = $value;
}
/**
* Get the shape flag
*
* @return int
*/
public function getSpFlag()
{
return $this->spFlag;
}
/**
* Set the shape index
*
* @param int $value
*/
public function setSpId($value)
{
$this->spId = $value;
}
/**
* Get the shape index
*
* @return int
*/
public function getSpId()
{
return $this->spId;
}
/**
* Set an option for the Shape Group Container
*
* @param int $property The number specifies the option
* @param mixed $value
*/
public function setOPT($property, $value)
{
$this->OPT[$property] = $value;
}
/**
* Get an option for the Shape Group Container
*
* @param int $property The number specifies the option
* @return mixed
*/
public function getOPT($property)
{
if (isset($this->OPT[$property])) {
return $this->OPT[$property];
}
return null;
}
/**
* Get the collection of options
*
* @return array
*/
public function getOPTCollection()
{
return $this->OPT;
}
/**
* Set cell coordinates of upper-left corner of shape
*
* @param string $value
*/
public function setStartCoordinates($value = 'A1')
{
$this->startCoordinates = $value;
}
/**
* Get cell coordinates of upper-left corner of shape
*
* @return string
*/
public function getStartCoordinates()
{
return $this->startCoordinates;
}
/**
* Set offset in x-direction of upper-left corner of shape measured in 1/1024 of column width
*
* @param int $startOffsetX
*/
public function setStartOffsetX($startOffsetX = 0)
{
$this->startOffsetX = $startOffsetX;
}
/**
* Get offset in x-direction of upper-left corner of shape measured in 1/1024 of column width
*
* @return int
*/
public function getStartOffsetX()
{
return $this->startOffsetX;
}
/**
* Set offset in y-direction of upper-left corner of shape measured in 1/256 of row height
*
* @param int $startOffsetY
*/
public function setStartOffsetY($startOffsetY = 0)
{
$this->startOffsetY = $startOffsetY;
}
/**
* Get offset in y-direction of upper-left corner of shape measured in 1/256 of row height
*
* @return int
*/
public function getStartOffsetY()
{
return $this->startOffsetY;
}
/**
* Set cell coordinates of bottom-right corner of shape
*
* @param string $value
*/
public function setEndCoordinates($value = 'A1')
{
$this->endCoordinates = $value;
}
/**
* Get cell coordinates of bottom-right corner of shape
*
* @return string
*/
public function getEndCoordinates()
{
return $this->endCoordinates;
}
/**
* Set offset in x-direction of bottom-right corner of shape measured in 1/1024 of column width
*
* @param int $startOffsetX
*/
public function setEndOffsetX($endOffsetX = 0)
{
$this->endOffsetX = $endOffsetX;
}
/**
* Get offset in x-direction of bottom-right corner of shape measured in 1/1024 of column width
*
* @return int
*/
public function getEndOffsetX()
{
return $this->endOffsetX;
}
/**
* Set offset in y-direction of bottom-right corner of shape measured in 1/256 of row height
*
* @param int $endOffsetY
*/
public function setEndOffsetY($endOffsetY = 0)
{
$this->endOffsetY = $endOffsetY;
}
/**
* Get offset in y-direction of bottom-right corner of shape measured in 1/256 of row height
*
* @return int
*/
public function getEndOffsetY()
{
return $this->endOffsetY;
}
/**
* Get the nesting level of this spContainer. This is the number of spgrContainers between this spContainer and
* the dgContainer. A value of 1 = immediately within first spgrContainer
* Higher nesting level occurs if and only if spContainer is part of a shape group
*
* @return int Nesting level
*/
public function getNestingLevel()
{
$nestingLevel = 0;
$parent = $this->getParent();
while ($parent instanceof PHPExcel_Shared_Escher_DgContainer_SpgrContainer) {
++$nestingLevel;
$parent = $parent->getParent();
}
return $nestingLevel;
}
}

196
extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer.php

@ -0,0 +1,196 @@
<?php
/**
* PHPExcel_Shared_Escher_DggContainer
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher_DggContainer
{
/**
* Maximum shape index of all shapes in all drawings increased by one
*
* @var int
*/
private $spIdMax;
/**
* Total number of drawings saved
*
* @var int
*/
private $cDgSaved;
/**
* Total number of shapes saved (including group shapes)
*
* @var int
*/
private $cSpSaved;
/**
* BLIP Store Container
*
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer
*/
private $bstoreContainer;
/**
* Array of options for the drawing group
*
* @var array
*/
private $OPT = array();
/**
* Array of identifier clusters containg information about the maximum shape identifiers
*
* @var array
*/
private $IDCLs = array();
/**
* Get maximum shape index of all shapes in all drawings (plus one)
*
* @return int
*/
public function getSpIdMax()
{
return $this->spIdMax;
}
/**
* Set maximum shape index of all shapes in all drawings (plus one)
*
* @param int
*/
public function setSpIdMax($value)
{
$this->spIdMax = $value;
}
/**
* Get total number of drawings saved
*
* @return int
*/
public function getCDgSaved()
{
return $this->cDgSaved;
}
/**
* Set total number of drawings saved
*
* @param int
*/
public function setCDgSaved($value)
{
$this->cDgSaved = $value;
}
/**
* Get total number of shapes saved (including group shapes)
*
* @return int
*/
public function getCSpSaved()
{
return $this->cSpSaved;
}
/**
* Set total number of shapes saved (including group shapes)
*
* @param int
*/
public function setCSpSaved($value)
{
$this->cSpSaved = $value;
}
/**
* Get BLIP Store Container
*
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer
*/
public function getBstoreContainer()
{
return $this->bstoreContainer;
}
/**
* Set BLIP Store Container
*
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer $bstoreContainer
*/
public function setBstoreContainer($bstoreContainer)
{
$this->bstoreContainer = $bstoreContainer;
}
/**
* Set an option for the drawing group
*
* @param int $property The number specifies the option
* @param mixed $value
*/
public function setOPT($property, $value)
{
$this->OPT[$property] = $value;
}
/**
* Get an option for the drawing group
*
* @param int $property The number specifies the option
* @return mixed
*/
public function getOPT($property)
{
if (isset($this->OPT[$property])) {
return $this->OPT[$property];
}
return null;
}
/**
* Get identifier clusters
*
* @return array
*/
public function getIDCLs()
{
return $this->IDCLs;
}
/**
* Set identifier clusters. array(<drawingId> => <max shape id>, ...)
*
* @param array $pValue
*/
public function setIDCLs($pValue)
{
$this->IDCLs = $pValue;
}
}

57
extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php

@ -0,0 +1,57 @@
<?php
/**
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher_DggContainer_BstoreContainer
{
/**
* BLIP Store Entries. Each of them holds one BLIP (Big Large Image or Picture)
*
* @var array
*/
private $BSECollection = array();
/**
* Add a BLIP Store Entry
*
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $BSE
*/
public function addBSE($BSE)
{
$this->BSECollection[] = $BSE;
$BSE->setParent($this);
}
/**
* Get the collection of BLIP Store Entries
*
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE[]
*/
public function getBSECollection()
{
return $this->BSECollection;
}
}

112
extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php

@ -0,0 +1,112 @@
<?php
/**
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE
{
const BLIPTYPE_ERROR = 0x00;
const BLIPTYPE_UNKNOWN = 0x01;
const BLIPTYPE_EMF = 0x02;
const BLIPTYPE_WMF = 0x03;
const BLIPTYPE_PICT = 0x04;
const BLIPTYPE_JPEG = 0x05;
const BLIPTYPE_PNG = 0x06;
const BLIPTYPE_DIB = 0x07;
const BLIPTYPE_TIFF = 0x11;
const BLIPTYPE_CMYKJPEG = 0x12;
/**
* The parent BLIP Store Entry Container
*
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer
*/
private $parent;
/**
* The BLIP (Big Large Image or Picture)
*
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip
*/
private $blip;
/**
* The BLIP type
*
* @var int
*/
private $blipType;
/**
* Set parent BLIP Store Entry Container
*
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* Get the BLIP
*
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip
*/
public function getBlip()
{
return $this->blip;
}
/**
* Set the BLIP
*
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip $blip
*/
public function setBlip($blip)
{
$this->blip = $blip;
$blip->setParent($this);
}
/**
* Get the BLIP type
*
* @return int
*/
public function getBlipType()
{
return $this->blipType;
}
/**
* Set the BLIP type
*
* @param int
*/
public function setBlipType($blipType)
{
$this->blipType = $blipType;
}
}

83
extend/PHPExcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php

@ -0,0 +1,83 @@
<?php
/**
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip
*
* Copyright (c) 2006 - 2015 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_Shared_Escher
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip
{
/**
* The parent BSE
*
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE
*/
private $parent;
/**
* Raw image data
*
* @var string
*/
private $data;
/**
* Get the raw image data
*
* @return string
*/
public function getData()
{
return $this->data;
}
/**
* Set the raw image data
*
* @param string
*/
public function setData($data)
{
$this->data = $data;
}
/**
* Set parent BSE
*
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $parent
*/
public function setParent($parent)
{
$this->parent = $parent;
}
/**
* Get parent BSE
*
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $parent
*/
public function getParent()
{
return $this->parent;
}
}

298
extend/PHPExcel/PHPExcel/Shared/Excel5.php

@ -0,0 +1,298 @@
<?php
/**
* PHPExcel_Shared_Excel5
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_Excel5
{
/**
* Get the width of a column in pixels. We use the relationship y = ceil(7x) where
* x is the width in intrinsic Excel units (measuring width in number of normal characters)
* This holds for Arial 10
*
* @param PHPExcel_Worksheet $sheet The sheet
* @param string $col The column
* @return integer The width in pixels
*/
public static function sizeCol($sheet, $col = 'A')
{
// default font of the workbook
$font = $sheet->getParent()->getDefaultStyle()->getFont();
$columnDimensions = $sheet->getColumnDimensions();
// first find the true column width in pixels (uncollapsed and unhidden)
if (isset($columnDimensions[$col]) and $columnDimensions[$col]->getWidth() != -1) {
// then we have column dimension with explicit width
$columnDimension = $columnDimensions[$col];
$width = $columnDimension->getWidth();
$pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font);
} elseif ($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, $font);
} else {
// 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
if (isset($columnDimensions[$col]) and !$columnDimensions[$col]->getVisible()) {
$effectivePixelWidth = 0;
} else {
$effectivePixelWidth = $pixelWidth;
}
return $effectivePixelWidth;
}
/**
* Convert the height of a cell from user's units to pixels. By interpolation
* the relationship is: y = 4/3x. If the height hasn't been set by the user we
* use the default value. If the row is hidden we use a value of zero.
*
* @param PHPExcel_Worksheet $sheet The sheet
* @param integer $row The row index (1-based)
* @return integer The width in pixels
*/
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)
if (isset($rowDimensions[$row]) and $rowDimensions[$row]->getRowHeight() != -1) {
// then we have a row dimension
$rowDimension = $rowDimensions[$row];
$rowHeight = $rowDimension->getRowHeight();
$pixelRowHeight = (int) ceil(4 * $rowHeight / 3); // here we assume Arial 10
} elseif ($sheet->getDefaultRowDimension()->getRowHeight() != -1) {
// then we have a default row dimension with explicit height
$defaultRowDimension = $sheet->getDefaultRowDimension();
$rowHeight = $defaultRowDimension->getRowHeight();
$pixelRowHeight = PHPExcel_Shared_Drawing::pointsToPixels($rowHeight);
} else {
// 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
if (isset($rowDimensions[$row]) and !$rowDimensions[$row]->getVisible()) {
$effectivePixelRowHeight = 0;
} else {
$effectivePixelRowHeight = $pixelRowHeight;
}
return $effectivePixelRowHeight;
}
/**
* Get the horizontal distance in pixels between two anchors
* The distanceX is found as sum of all the spanning columns widths minus correction for the two offsets
*
* @param PHPExcel_Worksheet $sheet
* @param string $startColumn
* @param integer $startOffsetX Offset within start cell measured in 1/1024 of the cell width
* @param string $endColumn
* @param integer $endOffsetX Offset within end cell measured in 1/1024 of the cell width
* @return integer Horizontal measured in pixels
*/
public static function getDistanceX(PHPExcel_Worksheet $sheet, $startColumn = 'A', $startOffsetX = 0, $endColumn = 'A', $endOffsetX = 0)
{
$distanceX = 0;
// add the widths of the spanning columns
$startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumn) - 1; // 1-based
$endColumnIndex = PHPExcel_Cell::columnIndexFromString($endColumn) - 1; // 1-based
for ($i = $startColumnIndex; $i <= $endColumnIndex; ++$i) {
$distanceX += self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($i));
}
// correct for offsetX in startcell
$distanceX -= (int) floor(self::sizeCol($sheet, $startColumn) * $startOffsetX / 1024);
// correct for offsetX in endcell
$distanceX -= (int) floor(self::sizeCol($sheet, $endColumn) * (1 - $endOffsetX / 1024));
return $distanceX;
}
/**
* Get the vertical distance in pixels between two anchors
* The distanceY is found as sum of all the spanning rows minus two offsets
*
* @param PHPExcel_Worksheet $sheet
* @param integer $startRow (1-based)
* @param integer $startOffsetY Offset within start cell measured in 1/256 of the cell height
* @param integer $endRow (1-based)
* @param integer $endOffsetY Offset within end cell measured in 1/256 of the cell height
* @return integer Vertical distance measured in pixels
*/
public static function getDistanceY(PHPExcel_Worksheet $sheet, $startRow = 1, $startOffsetY = 0, $endRow = 1, $endOffsetY = 0)
{
$distanceY = 0;
// add the widths of the spanning rows
for ($row = $startRow; $row <= $endRow; ++$row) {
$distanceY += self::sizeRow($sheet, $row);
}
// correct for offsetX in startcell
$distanceY -= (int) floor(self::sizeRow($sheet, $startRow) * $startOffsetY / 256);
// correct for offsetX in endcell
$distanceY -= (int) floor(self::sizeRow($sheet, $endRow) * (1 - $endOffsetY / 256));
return $distanceY;
}
/**
* Convert 1-cell anchor coordinates to 2-cell anchor coordinates
* This function is ported from PEAR Spreadsheet_Writer_Excel with small modifications
*
* Calculate the vertices that define the position of the image as required by
* the OBJ record.
*
* +------------+------------+
* | A | B |
* +-----+------------+------------+
* | |(x1,y1) | |
* | 1 |(A1)._______|______ |
* | | | | |
* | | | | |
* +-----+----| BITMAP |-----+
* | | | | |
* | 2 | |______________. |
* | | | (B2)|
* | | | (x2,y2)|
* +---- +------------+------------+
*
* Example of a bitmap that covers some of the area from cell A1 to cell B2.
*
* Based on the width and height of the bitmap we need to calculate 8 vars:
* $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
* The width and height of the cells are also variable and have to be taken into
* account.
* The values of $col_start and $row_start are passed in from the calling
* function. The values of $col_end and $row_end are calculated by subtracting
* the width and height of the bitmap from the width and height of the
* underlying cells.
* The vertices are expressed as a percentage of the underlying cell width as
* follows (rhs values are in pixels):
*
* x1 = X / W *1024
* y1 = Y / H *256
* x2 = (X-1) / W *1024
* y2 = (Y-1) / H *256
*
* Where: X is distance from the left side of the underlying cell
* Y is distance from the top of the underlying cell
* W is the width of the cell
* H is the height of the cell
*
* @param PHPExcel_Worksheet $sheet
* @param string $coordinates E.g. 'A1'
* @param integer $offsetX Horizontal offset in pixels
* @param integer $offsetY Vertical offset in pixels
* @param integer $width Width in pixels
* @param integer $height Height in pixels
* @return array
*/
public static function oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height)
{
list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinates);
$col_start = PHPExcel_Cell::columnIndexFromString($column) - 1;
$row_start = $row - 1;
$x1 = $offsetX;
$y1 = $offsetY;
// Initialise end cell to the same as the start cell
$col_end = $col_start; // Col containing lower right corner of object
$row_end = $row_start; // Row containing bottom right corner of object
// Zero the specified offset if greater than the cell dimensions
if ($x1 >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start))) {
$x1 = 0;
}
if ($y1 >= self::sizeRow($sheet, $row_start + 1)) {
$y1 = 0;
}
$width = $width + $x1 -1;
$height = $height + $y1 -1;
// Subtract the underlying cell widths to find the end cell of the image
while ($width >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end))) {
$width -= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end));
++$col_end;
}
// Subtract the underlying cell heights to find the end cell of the image
while ($height >= self::sizeRow($sheet, $row_end + 1)) {
$height -= self::sizeRow($sheet, $row_end + 1);
++$row_end;
}
// Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
// with zero height or width.
if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) {
return;
}
if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) == 0) {
return;
}
if (self::sizeRow($sheet, $row_start + 1) == 0) {
return;
}
if (self::sizeRow($sheet, $row_end + 1) == 0) {
return;
}
// 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 + 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);
$twoAnchor = array(
'startCoordinates' => $startCoordinates,
'startOffsetX' => $x1,
'startOffsetY' => $y1,
'endCoordinates' => $endCoordinates,
'endOffsetX' => $x2,
'endOffsetY' => $y2,
);
return $twoAnchor;
}
}

180
extend/PHPExcel/PHPExcel/Shared/File.php

@ -0,0 +1,180 @@
<?php
/**
* PHPExcel_Shared_File
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_File
{
/*
* Use Temp or File Upload Temp for temporary files
*
* @protected
* @var boolean
*/
protected static $useUploadTempDirectory = false;
/**
* Set the flag indicating whether the File Upload Temp directory should be used for temporary files
*
* @param boolean $useUploadTempDir Use File Upload Temporary directory (true or false)
*/
public static function setUseUploadTempDirectory($useUploadTempDir = false)
{
self::$useUploadTempDirectory = (boolean) $useUploadTempDir;
}
/**
* Get the flag indicating whether the File Upload Temp directory should be used for temporary files
*
* @return boolean Use File Upload Temporary directory (true or false)
*/
public static function getUseUploadTempDirectory()
{
return self::$useUploadTempDirectory;
}
/**
* Verify if a file exists
*
* @param string $pFilename Filename
* @return bool
*/
public static function file_exists($pFilename)
{
// Sick construction, but it seems that
// file_exists returns strange values when
// doing the original file_exists on ZIP archives...
if (strtolower(substr($pFilename, 0, 3)) == 'zip') {
// Open ZIP file and verify if the file exists
$zipFile = substr($pFilename, 6, strpos($pFilename, '#') - 6);
$archiveFile = substr($pFilename, strpos($pFilename, '#') + 1);
$zip = new ZipArchive();
if ($zip->open($zipFile) === true) {
$returnValue = ($zip->getFromName($archiveFile) !== false);
$zip->close();
return $returnValue;
} else {
return false;
}
} else {
// Regular file_exists
return file_exists($pFilename);
}
}
/**
* Returns canonicalized absolute pathname, also for ZIP archives
*
* @param string $pFilename
* @return string
*/
public static function realpath($pFilename)
{
// Returnvalue
$returnValue = '';
// Try using realpath()
if (file_exists($pFilename)) {
$returnValue = realpath($pFilename);
}
// Found something?
if ($returnValue == '' || ($returnValue === null)) {
$pathArray = explode('/', $pFilename);
while (in_array('..', $pathArray) && $pathArray[0] != '..') {
for ($i = 0; $i < count($pathArray); ++$i) {
if ($pathArray[$i] == '..' && $i > 0) {
unset($pathArray[$i]);
unset($pathArray[$i - 1]);
break;
}
}
}
$returnValue = implode('/', $pathArray);
}
// Return
return $returnValue;
}
/**
* Get the systems temporary directory.
*
* @return string
*/
public static function sys_get_temp_dir()
{
if (self::$useUploadTempDirectory) {
// use upload-directory when defined to allow running on environments having very restricted
// open_basedir configs
if (ini_get('upload_tmp_dir') !== false) {
if ($temp = ini_get('upload_tmp_dir')) {
if (file_exists($temp)) {
return realpath($temp);
}
}
}
}
// 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')) {
if ((!empty($temp)) && (file_exists($temp))) {
return realpath($temp);
}
}
if ($temp = getenv('TEMP')) {
if ((!empty($temp)) && (file_exists($temp))) {
return realpath($temp);
}
}
if ($temp = getenv('TMPDIR')) {
if ((!empty($temp)) && (file_exists($temp))) {
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
// There should be no problem with the 5.2.4 Suhosin realpath() bug, because this line should only
// be called if we're running 5.2.1 or earlier
return realpath(sys_get_temp_dir());
}
}

741
extend/PHPExcel/PHPExcel/Shared/Font.php

@ -0,0 +1,741 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Shared_Font
*
* @category PHPExcel
* @package PHPExcel_Shared
* @copyright Copyright (c) 2006 - 2015 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';
private static $autoSizeMethods = array(
self::AUTOSIZE_METHOD_APPROX,
self::AUTOSIZE_METHOD_EXACT,
);
/** Character set codes used by BIFF5-8 in Font records */
const CHARSET_ANSI_LATIN = 0x00;
const CHARSET_SYSTEM_DEFAULT = 0x01;
const CHARSET_SYMBOL = 0x02;
const CHARSET_APPLE_ROMAN = 0x4D;
const CHARSET_ANSI_JAPANESE_SHIFTJIS = 0x80;
const CHARSET_ANSI_KOREAN_HANGUL = 0x81;
const CHARSET_ANSI_KOREAN_JOHAB = 0x82;
const CHARSET_ANSI_CHINESE_SIMIPLIFIED = 0x86; // gb2312
const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88; // big5
const CHARSET_ANSI_GREEK = 0xA1;
const CHARSET_ANSI_TURKISH = 0xA2;
const CHARSET_ANSI_VIETNAMESE = 0xA3;
const CHARSET_ANSI_HEBREW = 0xB1;
const CHARSET_ANSI_ARABIC = 0xB2;
const CHARSET_ANSI_BALTIC = 0xBA;
const CHARSET_ANSI_CYRILLIC = 0xCC;
const CHARSET_ANSI_THAI = 0xDD;
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
* @return boolean Success or failure
*/
public static function setAutoSizeMethod($pValue = self::AUTOSIZE_METHOD_APPROX)
{
if (!in_array($pValue, self::$autoSizeMethods)) {
return false;
}
self::$autoSizeMethod = $pValue;
return true;
}
/**
* 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:
* <ul>
* <li>C:/Windows/Fonts/</li>
* <li>/usr/share/fonts/truetype/</li>
* <li>~/.fonts/</li>
* </ul>
*
* @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
*
* @param PHPExcel_Style_Font $font Font object
* @param PHPExcel_RichText|string $cellText Text to calculate width
* @param integer $rotation Rotation angle
* @param PHPExcel_Style_Font|NULL $defaultFont Font object
* @return integer Column width
*/
public static function calculateColumnWidth(PHPExcel_Style_Font $font, $cellText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null)
{
// If it is rich text, use plain text
if ($cellText instanceof PHPExcel_RichText) {
$cellText = $cellText->getPlainText();
}
// Special case if there are one or more newline characters ("\n")
if (strpos($cellText, "\n") !== false) {
$lineTexts = explode("\n", $cellText);
$lineWidths = array();
foreach ($lineTexts as $lineText) {
$lineWidths[] = self::calculateColumnWidth($font, $lineText, $rotation = 0, $defaultFont);
}
return max($lineWidths); // width of longest line in cell
}
// Try to get the exact text width in pixels
$approximate = self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX;
if (!$approximate) {
$columnWidthAdjust = ceil(self::getTextWidthPixelsExact('n', $font, 0) * 1.07);
try {
// Width of text in pixels excl. padding
// and addition because Excel adds some padding, just use approx width of 'n' glyph
$columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation) + $columnWidthAdjust;
} catch (PHPExcel_Exception $e) {
$approximate = true;
}
}
if ($approximate) {
$columnWidthAdjust = self::getTextWidthPixelsApprox('n', $font, 0);
// Width of text in pixels excl. padding, approximation
// and addition because Excel adds some padding, just use approx width of 'n' glyph
$columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation) + $columnWidthAdjust;
}
// 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 PHPExcel_Exception
*/
public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0)
{
if (!function_exists('imagettfbbox')) {
throw new PHPExcel_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];
// 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));
// value 8 was set because of experience in different exports at Arial 10 font.
$columnWidth = (int) (8 * 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) {
if ($rotation == -165) {
// stacked text
$columnWidth = 4; // approximation
} else {
// rotated text
$columnWidth = $columnWidth * cos(deg2rad($rotation))
+ $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation
}
}
// pixel width is an integer
return (int) $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 = 11)
{
return (int) ((4 / 3) * $fontSizeInPoints);
}
/**
* Calculate an (approximate) pixel size, based on inch size
*
* @param int $sizeInInch Font size (in inch)
* @return int Size (in pixels)
*/
public static function inchSizeToPixels($sizeInInch = 1)
{
return ($sizeInInch * 96);
}
/**
* Calculate an (approximate) pixel size, based on centimeter size
*
* @param int $sizeInCm Font size (in centimeters)
* @return int Size (in pixels)
*/
public static function centimeterSizeToPixels($sizeInCm = 1)
{
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 PHPExcel_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 PHPExcel_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 PHPExcel_Exception('TrueType Font file not found');
}
return $fontFile;
}
/**
* Returns the associated charset for the font name.
*
* @param string $name Font name
* @return int Character set code
*/
public static function getCharsetFromFontName($name)
{
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;
default:
return self::CHARSET_ANSI_LATIN;
}
}
/**
* 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;
}
}

16
extend/PHPExcel/PHPExcel/Shared/JAMA/CHANGELOG.TXT

@ -0,0 +1,16 @@
Mar 1, 2005 11:15 AST by PM
+ For consistency, renamed Math.php to Maths.java, utils to util,
tests to test, docs to doc -
+ Removed conditional logic from top of Matrix class.
+ Switched to using hypo function in Maths.php for all php-hypot calls.
NOTE TO SELF: Need to make sure that all decompositions have been
switched over to using the bundled hypo.
Feb 25, 2005 at 10:00 AST by PM
+ Recommend using simpler Error.php instead of JAMA_Error.php but
can be persuaded otherwise.

148
extend/PHPExcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php

@ -0,0 +1,148 @@
<?php
/**
* @package JAMA
*
* Cholesky decomposition class
*
* For a symmetric, positive definite matrix A, the Cholesky decomposition
* is an lower triangular matrix L so that A = L*L'.
*
* If the matrix is not symmetric or positive definite, the constructor
* returns a partial decomposition and sets an internal flag that may
* be queried by the isSPD() method.
*
* @author Paul Meagher
* @author Michael Bommarito
* @version 1.2
*/
class CholeskyDecomposition
{
/**
* Decomposition storage
* @var array
* @access private
*/
private $L = array();
/**
* Matrix row and column dimension
* @var int
* @access private
*/
private $m;
/**
* Symmetric positive definite flag
* @var boolean
* @access private
*/
private $isspd = true;
/**
* CholeskyDecomposition
*
* Class constructor - decomposes symmetric positive definite matrix
* @param mixed Matrix square symmetric positive definite matrix
*/
public function __construct($A = null)
{
if ($A instanceof Matrix) {
$this->L = $A->getArray();
$this->m = $A->getRowDimension();
for ($i = 0; $i < $this->m; ++$i) {
for ($j = $i; $j < $this->m; ++$j) {
for ($sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; --$k) {
$sum -= $this->L[$i][$k] * $this->L[$j][$k];
}
if ($i == $j) {
if ($sum >= 0) {
$this->L[$i][$i] = sqrt($sum);
} else {
$this->isspd = false;
}
} else {
if ($this->L[$i][$i] != 0) {
$this->L[$j][$i] = $sum / $this->L[$i][$i];
}
}
}
for ($k = $i+1; $k < $this->m; ++$k) {
$this->L[$i][$k] = 0.0;
}
}
} else {
throw new PHPExcel_Calculation_Exception(JAMAError(ARGUMENT_TYPE_EXCEPTION));
}
} // function __construct()
/**
* Is the matrix symmetric and positive definite?
*
* @return boolean
*/
public function isSPD()
{
return $this->isspd;
} // function isSPD()
/**
* getL
*
* Return triangular factor.
* @return Matrix Lower triangular matrix
*/
public function getL()
{
return new Matrix($this->L);
} // function getL()
/**
* Solve A*X = B
*
* @param $B Row-equal matrix
* @return Matrix L * L' * X = B
*/
public function solve($B = null)
{
if ($B instanceof Matrix) {
if ($B->getRowDimension() == $this->m) {
if ($this->isspd) {
$X = $B->getArrayCopy();
$nx = $B->getColumnDimension();
for ($k = 0; $k < $this->m; ++$k) {
for ($i = $k + 1; $i < $this->m; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k];
}
}
for ($j = 0; $j < $nx; ++$j) {
$X[$k][$j] /= $this->L[$k][$k];
}
}
for ($k = $this->m - 1; $k >= 0; --$k) {
for ($j = 0; $j < $nx; ++$j) {
$X[$k][$j] /= $this->L[$k][$k];
}
for ($i = 0; $i < $k; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i];
}
}
}
return new Matrix($X, $this->m, $nx);
} else {
throw new PHPExcel_Calculation_Exception(JAMAError(MatrixSPDException));
}
} else {
throw new PHPExcel_Calculation_Exception(JAMAError(MATRIX_DIMENSION_EXCEPTION));
}
} else {
throw new PHPExcel_Calculation_Exception(JAMAError(ARGUMENT_TYPE_EXCEPTION));
}
} // function solve()
}

864
extend/PHPExcel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php

@ -0,0 +1,864 @@
<?php
/**
* @package JAMA
*
* Class to obtain eigenvalues and eigenvectors of a real matrix.
*
* If A is symmetric, then A = V*D*V' where the eigenvalue matrix D
* is diagonal and the eigenvector matrix V is orthogonal (i.e.
* A = V.times(D.times(V.transpose())) and V.times(V.transpose())
* equals the identity matrix).
*
* If A is not symmetric, then the eigenvalue matrix D is block diagonal
* with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
* lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda]. The
* columns of V represent the eigenvectors in the sense that A*V = V*D,
* i.e. A.times(V) equals V.times(D). The matrix V may be badly
* conditioned, or even singular, so the validity of the equation
* A = V*D*inverse(V) depends upon V.cond().
*
* @author Paul Meagher
* @license PHP v3.0
* @version 1.1
*/
class EigenvalueDecomposition
{
/**
* Row and column dimension (square matrix).
* @var int
*/
private $n;
/**
* Internal symmetry flag.
* @var int
*/
private $issymmetric;
/**
* Arrays for internal storage of eigenvalues.
* @var array
*/
private $d = array();
private $e = array();
/**
* Array for internal storage of eigenvectors.
* @var array
*/
private $V = array();
/**
* Array for internal storage of nonsymmetric Hessenberg form.
* @var array
*/
private $H = array();
/**
* Working storage for nonsymmetric algorithm.
* @var array
*/
private $ort;
/**
* Used for complex scalar division.
* @var float
*/
private $cdivr;
private $cdivi;
/**
* Symmetric Householder reduction to tridiagonal form.
*
* @access private
*/
private function tred2()
{
// This is derived from the Algol procedures tred2 by
// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutine in EISPACK.
$this->d = $this->V[$this->n-1];
// Householder reduction to tridiagonal form.
for ($i = $this->n-1; $i > 0; --$i) {
$i_ = $i -1;
// Scale to avoid under/overflow.
$h = $scale = 0.0;
$scale += array_sum(array_map(abs, $this->d));
if ($scale == 0.0) {
$this->e[$i] = $this->d[$i_];
$this->d = array_slice($this->V[$i_], 0, $i_);
for ($j = 0; $j < $i; ++$j) {
$this->V[$j][$i] = $this->V[$i][$j] = 0.0;
}
} else {
// Generate Householder vector.
for ($k = 0; $k < $i; ++$k) {
$this->d[$k] /= $scale;
$h += pow($this->d[$k], 2);
}
$f = $this->d[$i_];
$g = sqrt($h);
if ($f > 0) {
$g = -$g;
}
$this->e[$i] = $scale * $g;
$h = $h - $f * $g;
$this->d[$i_] = $f - $g;
for ($j = 0; $j < $i; ++$j) {
$this->e[$j] = 0.0;
}
// Apply similarity transformation to remaining columns.
for ($j = 0; $j < $i; ++$j) {
$f = $this->d[$j];
$this->V[$j][$i] = $f;
$g = $this->e[$j] + $this->V[$j][$j] * $f;
for ($k = $j+1; $k <= $i_; ++$k) {
$g += $this->V[$k][$j] * $this->d[$k];
$this->e[$k] += $this->V[$k][$j] * $f;
}
$this->e[$j] = $g;
}
$f = 0.0;
for ($j = 0; $j < $i; ++$j) {
$this->e[$j] /= $h;
$f += $this->e[$j] * $this->d[$j];
}
$hh = $f / (2 * $h);
for ($j=0; $j < $i; ++$j) {
$this->e[$j] -= $hh * $this->d[$j];
}
for ($j = 0; $j < $i; ++$j) {
$f = $this->d[$j];
$g = $this->e[$j];
for ($k = $j; $k <= $i_; ++$k) {
$this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]);
}
$this->d[$j] = $this->V[$i-1][$j];
$this->V[$i][$j] = 0.0;
}
}
$this->d[$i] = $h;
}
// Accumulate transformations.
for ($i = 0; $i < $this->n-1; ++$i) {
$this->V[$this->n-1][$i] = $this->V[$i][$i];
$this->V[$i][$i] = 1.0;
$h = $this->d[$i+1];
if ($h != 0.0) {
for ($k = 0; $k <= $i; ++$k) {
$this->d[$k] = $this->V[$k][$i+1] / $h;
}
for ($j = 0; $j <= $i; ++$j) {
$g = 0.0;
for ($k = 0; $k <= $i; ++$k) {
$g += $this->V[$k][$i+1] * $this->V[$k][$j];
}
for ($k = 0; $k <= $i; ++$k) {
$this->V[$k][$j] -= $g * $this->d[$k];
}
}
}
for ($k = 0; $k <= $i; ++$k) {
$this->V[$k][$i+1] = 0.0;
}
}
$this->d = $this->V[$this->n-1];
$this->V[$this->n-1] = array_fill(0, $j, 0.0);
$this->V[$this->n-1][$this->n-1] = 1.0;
$this->e[0] = 0.0;
}
/**
* Symmetric tridiagonal QL algorithm.
*
* This is derived from the Algol procedures tql2, by
* Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
* Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
* Fortran subroutine in EISPACK.
*
* @access private
*/
private function tql2()
{
for ($i = 1; $i < $this->n; ++$i) {
$this->e[$i-1] = $this->e[$i];
}
$this->e[$this->n-1] = 0.0;
$f = 0.0;
$tst1 = 0.0;
$eps = pow(2.0, -52.0);
for ($l = 0; $l < $this->n; ++$l) {
// Find small subdiagonal element
$tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l]));
$m = $l;
while ($m < $this->n) {
if (abs($this->e[$m]) <= $eps * $tst1) {
break;
}
++$m;
}
// If m == l, $this->d[l] is an eigenvalue,
// otherwise, iterate.
if ($m > $l) {
$iter = 0;
do {
// Could check iteration count here.
$iter += 1;
// Compute implicit shift
$g = $this->d[$l];
$p = ($this->d[$l+1] - $g) / (2.0 * $this->e[$l]);
$r = hypo($p, 1.0);
if ($p < 0) {
$r *= -1;
}
$this->d[$l] = $this->e[$l] / ($p + $r);
$this->d[$l+1] = $this->e[$l] * ($p + $r);
$dl1 = $this->d[$l+1];
$h = $g - $this->d[$l];
for ($i = $l + 2; $i < $this->n; ++$i) {
$this->d[$i] -= $h;
}
$f += $h;
// Implicit QL transformation.
$p = $this->d[$m];
$c = 1.0;
$c2 = $c3 = $c;
$el1 = $this->e[$l + 1];
$s = $s2 = 0.0;
for ($i = $m-1; $i >= $l; --$i) {
$c3 = $c2;
$c2 = $c;
$s2 = $s;
$g = $c * $this->e[$i];
$h = $c * $p;
$r = hypo($p, $this->e[$i]);
$this->e[$i+1] = $s * $r;
$s = $this->e[$i] / $r;
$c = $p / $r;
$p = $c * $this->d[$i] - $s * $g;
$this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]);
// Accumulate transformation.
for ($k = 0; $k < $this->n; ++$k) {
$h = $this->V[$k][$i+1];
$this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h;
$this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h;
}
}
$p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1;
$this->e[$l] = $s * $p;
$this->d[$l] = $c * $p;
// Check for convergence.
} while (abs($this->e[$l]) > $eps * $tst1);
}
$this->d[$l] = $this->d[$l] + $f;
$this->e[$l] = 0.0;
}
// Sort eigenvalues and corresponding vectors.
for ($i = 0; $i < $this->n - 1; ++$i) {
$k = $i;
$p = $this->d[$i];
for ($j = $i+1; $j < $this->n; ++$j) {
if ($this->d[$j] < $p) {
$k = $j;
$p = $this->d[$j];
}
}
if ($k != $i) {
$this->d[$k] = $this->d[$i];
$this->d[$i] = $p;
for ($j = 0; $j < $this->n; ++$j) {
$p = $this->V[$j][$i];
$this->V[$j][$i] = $this->V[$j][$k];
$this->V[$j][$k] = $p;
}
}
}
}
/**
* Nonsymmetric reduction to Hessenberg form.
*
* This is derived from the Algol procedures orthes and ortran,
* by Martin and Wilkinson, Handbook for Auto. Comp.,
* Vol.ii-Linear Algebra, and the corresponding
* Fortran subroutines in EISPACK.
*
* @access private
*/
private function orthes()
{
$low = 0;
$high = $this->n-1;
for ($m = $low+1; $m <= $high-1; ++$m) {
// Scale column.
$scale = 0.0;
for ($i = $m; $i <= $high; ++$i) {
$scale = $scale + abs($this->H[$i][$m-1]);
}
if ($scale != 0.0) {
// Compute Householder transformation.
$h = 0.0;
for ($i = $high; $i >= $m; --$i) {
$this->ort[$i] = $this->H[$i][$m-1] / $scale;
$h += $this->ort[$i] * $this->ort[$i];
}
$g = sqrt($h);
if ($this->ort[$m] > 0) {
$g *= -1;
}
$h -= $this->ort[$m] * $g;
$this->ort[$m] -= $g;
// Apply Householder similarity transformation
// H = (I -u * u' / h) * H * (I -u * u') / h)
for ($j = $m; $j < $this->n; ++$j) {
$f = 0.0;
for ($i = $high; $i >= $m; --$i) {
$f += $this->ort[$i] * $this->H[$i][$j];
}
$f /= $h;
for ($i = $m; $i <= $high; ++$i) {
$this->H[$i][$j] -= $f * $this->ort[$i];
}
}
for ($i = 0; $i <= $high; ++$i) {
$f = 0.0;
for ($j = $high; $j >= $m; --$j) {
$f += $this->ort[$j] * $this->H[$i][$j];
}
$f = $f / $h;
for ($j = $m; $j <= $high; ++$j) {
$this->H[$i][$j] -= $f * $this->ort[$j];
}
}
$this->ort[$m] = $scale * $this->ort[$m];
$this->H[$m][$m-1] = $scale * $g;
}
}
// Accumulate transformations (Algol's ortran).
for ($i = 0; $i < $this->n; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
$this->V[$i][$j] = ($i == $j ? 1.0 : 0.0);
}
}
for ($m = $high-1; $m >= $low+1; --$m) {
if ($this->H[$m][$m-1] != 0.0) {
for ($i = $m+1; $i <= $high; ++$i) {
$this->ort[$i] = $this->H[$i][$m-1];
}
for ($j = $m; $j <= $high; ++$j) {
$g = 0.0;
for ($i = $m; $i <= $high; ++$i) {
$g += $this->ort[$i] * $this->V[$i][$j];
}
// Double division avoids possible underflow
$g = ($g / $this->ort[$m]) / $this->H[$m][$m-1];
for ($i = $m; $i <= $high; ++$i) {
$this->V[$i][$j] += $g * $this->ort[$i];
}
}
}
}
}
/**
* Performs complex division.
*
* @access private
*/
private function cdiv($xr, $xi, $yr, $yi)
{
if (abs($yr) > abs($yi)) {
$r = $yi / $yr;
$d = $yr + $r * $yi;
$this->cdivr = ($xr + $r * $xi) / $d;
$this->cdivi = ($xi - $r * $xr) / $d;
} else {
$r = $yr / $yi;
$d = $yi + $r * $yr;
$this->cdivr = ($r * $xr + $xi) / $d;
$this->cdivi = ($r * $xi - $xr) / $d;
}
}
/**
* Nonsymmetric reduction from Hessenberg to real Schur form.
*
* Code is derived from the Algol procedure hqr2,
* by Martin and Wilkinson, Handbook for Auto. Comp.,
* Vol.ii-Linear Algebra, and the corresponding
* Fortran subroutine in EISPACK.
*
* @access private
*/
private function hqr2()
{
// Initialize
$nn = $this->n;
$n = $nn - 1;
$low = 0;
$high = $nn - 1;
$eps = pow(2.0, -52.0);
$exshift = 0.0;
$p = $q = $r = $s = $z = 0;
// Store roots isolated by balanc and compute matrix norm
$norm = 0.0;
for ($i = 0; $i < $nn; ++$i) {
if (($i < $low) or ($i > $high)) {
$this->d[$i] = $this->H[$i][$i];
$this->e[$i] = 0.0;
}
for ($j = max($i-1, 0); $j < $nn; ++$j) {
$norm = $norm + abs($this->H[$i][$j]);
}
}
// Outer loop over eigenvalue index
$iter = 0;
while ($n >= $low) {
// Look for single small sub-diagonal element
$l = $n;
while ($l > $low) {
$s = abs($this->H[$l-1][$l-1]) + abs($this->H[$l][$l]);
if ($s == 0.0) {
$s = $norm;
}
if (abs($this->H[$l][$l-1]) < $eps * $s) {
break;
}
--$l;
}
// Check for convergence
// One root found
if ($l == $n) {
$this->H[$n][$n] = $this->H[$n][$n] + $exshift;
$this->d[$n] = $this->H[$n][$n];
$this->e[$n] = 0.0;
--$n;
$iter = 0;
// Two roots found
} elseif ($l == $n-1) {
$w = $this->H[$n][$n-1] * $this->H[$n-1][$n];
$p = ($this->H[$n-1][$n-1] - $this->H[$n][$n]) / 2.0;
$q = $p * $p + $w;
$z = sqrt(abs($q));
$this->H[$n][$n] = $this->H[$n][$n] + $exshift;
$this->H[$n-1][$n-1] = $this->H[$n-1][$n-1] + $exshift;
$x = $this->H[$n][$n];
// Real pair
if ($q >= 0) {
if ($p >= 0) {
$z = $p + $z;
} else {
$z = $p - $z;
}
$this->d[$n-1] = $x + $z;
$this->d[$n] = $this->d[$n-1];
if ($z != 0.0) {
$this->d[$n] = $x - $w / $z;
}
$this->e[$n-1] = 0.0;
$this->e[$n] = 0.0;
$x = $this->H[$n][$n-1];
$s = abs($x) + abs($z);
$p = $x / $s;
$q = $z / $s;
$r = sqrt($p * $p + $q * $q);
$p = $p / $r;
$q = $q / $r;
// Row modification
for ($j = $n-1; $j < $nn; ++$j) {
$z = $this->H[$n-1][$j];
$this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j];
$this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z;
}
// Column modification
for ($i = 0; $i <= $n; ++$i) {
$z = $this->H[$i][$n-1];
$this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n];
$this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z;
}
// Accumulate transformations
for ($i = $low; $i <= $high; ++$i) {
$z = $this->V[$i][$n-1];
$this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n];
$this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z;
}
// Complex pair
} else {
$this->d[$n-1] = $x + $p;
$this->d[$n] = $x + $p;
$this->e[$n-1] = $z;
$this->e[$n] = -$z;
}
$n = $n - 2;
$iter = 0;
// No convergence yet
} else {
// Form shift
$x = $this->H[$n][$n];
$y = 0.0;
$w = 0.0;
if ($l < $n) {
$y = $this->H[$n-1][$n-1];
$w = $this->H[$n][$n-1] * $this->H[$n-1][$n];
}
// Wilkinson's original ad hoc shift
if ($iter == 10) {
$exshift += $x;
for ($i = $low; $i <= $n; ++$i) {
$this->H[$i][$i] -= $x;
}
$s = abs($this->H[$n][$n-1]) + abs($this->H[$n-1][$n-2]);
$x = $y = 0.75 * $s;
$w = -0.4375 * $s * $s;
}
// MATLAB's new ad hoc shift
if ($iter == 30) {
$s = ($y - $x) / 2.0;
$s = $s * $s + $w;
if ($s > 0) {
$s = sqrt($s);
if ($y < $x) {
$s = -$s;
}
$s = $x - $w / (($y - $x) / 2.0 + $s);
for ($i = $low; $i <= $n; ++$i) {
$this->H[$i][$i] -= $s;
}
$exshift += $s;
$x = $y = $w = 0.964;
}
}
// Could check iteration count here.
$iter = $iter + 1;
// Look for two consecutive small sub-diagonal elements
$m = $n - 2;
while ($m >= $l) {
$z = $this->H[$m][$m];
$r = $x - $z;
$s = $y - $z;
$p = ($r * $s - $w) / $this->H[$m+1][$m] + $this->H[$m][$m+1];
$q = $this->H[$m+1][$m+1] - $z - $r - $s;
$r = $this->H[$m+2][$m+1];
$s = abs($p) + abs($q) + abs($r);
$p = $p / $s;
$q = $q / $s;
$r = $r / $s;
if ($m == $l) {
break;
}
if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) <
$eps * (abs($p) * (abs($this->H[$m-1][$m-1]) + abs($z) + abs($this->H[$m+1][$m+1])))) {
break;
}
--$m;
}
for ($i = $m + 2; $i <= $n; ++$i) {
$this->H[$i][$i-2] = 0.0;
if ($i > $m+2) {
$this->H[$i][$i-3] = 0.0;
}
}
// Double QR step involving rows l:n and columns m:n
for ($k = $m; $k <= $n-1; ++$k) {
$notlast = ($k != $n-1);
if ($k != $m) {
$p = $this->H[$k][$k-1];
$q = $this->H[$k+1][$k-1];
$r = ($notlast ? $this->H[$k+2][$k-1] : 0.0);
$x = abs($p) + abs($q) + abs($r);
if ($x != 0.0) {
$p = $p / $x;
$q = $q / $x;
$r = $r / $x;
}
}
if ($x == 0.0) {
break;
}
$s = sqrt($p * $p + $q * $q + $r * $r);
if ($p < 0) {
$s = -$s;
}
if ($s != 0) {
if ($k != $m) {
$this->H[$k][$k-1] = -$s * $x;
} elseif ($l != $m) {
$this->H[$k][$k-1] = -$this->H[$k][$k-1];
}
$p = $p + $s;
$x = $p / $s;
$y = $q / $s;
$z = $r / $s;
$q = $q / $p;
$r = $r / $p;
// Row modification
for ($j = $k; $j < $nn; ++$j) {
$p = $this->H[$k][$j] + $q * $this->H[$k+1][$j];
if ($notlast) {
$p = $p + $r * $this->H[$k+2][$j];
$this->H[$k+2][$j] = $this->H[$k+2][$j] - $p * $z;
}
$this->H[$k][$j] = $this->H[$k][$j] - $p * $x;
$this->H[$k+1][$j] = $this->H[$k+1][$j] - $p * $y;
}
// Column modification
for ($i = 0; $i <= min($n, $k+3); ++$i) {
$p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k+1];
if ($notlast) {
$p = $p + $z * $this->H[$i][$k+2];
$this->H[$i][$k+2] = $this->H[$i][$k+2] - $p * $r;
}
$this->H[$i][$k] = $this->H[$i][$k] - $p;
$this->H[$i][$k+1] = $this->H[$i][$k+1] - $p * $q;
}
// Accumulate transformations
for ($i = $low; $i <= $high; ++$i) {
$p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k+1];
if ($notlast) {
$p = $p + $z * $this->V[$i][$k+2];
$this->V[$i][$k+2] = $this->V[$i][$k+2] - $p * $r;
}
$this->V[$i][$k] = $this->V[$i][$k] - $p;
$this->V[$i][$k+1] = $this->V[$i][$k+1] - $p * $q;
}
} // ($s != 0)
} // k loop
} // check convergence
} // while ($n >= $low)
// Backsubstitute to find vectors of upper triangular form
if ($norm == 0.0) {
return;
}
for ($n = $nn-1; $n >= 0; --$n) {
$p = $this->d[$n];
$q = $this->e[$n];
// Real vector
if ($q == 0) {
$l = $n;
$this->H[$n][$n] = 1.0;
for ($i = $n-1; $i >= 0; --$i) {
$w = $this->H[$i][$i] - $p;
$r = 0.0;
for ($j = $l; $j <= $n; ++$j) {
$r = $r + $this->H[$i][$j] * $this->H[$j][$n];
}
if ($this->e[$i] < 0.0) {
$z = $w;
$s = $r;
} else {
$l = $i;
if ($this->e[$i] == 0.0) {
if ($w != 0.0) {
$this->H[$i][$n] = -$r / $w;
} else {
$this->H[$i][$n] = -$r / ($eps * $norm);
}
// Solve real equations
} else {
$x = $this->H[$i][$i+1];
$y = $this->H[$i+1][$i];
$q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i];
$t = ($x * $s - $z * $r) / $q;
$this->H[$i][$n] = $t;
if (abs($x) > abs($z)) {
$this->H[$i+1][$n] = (-$r - $w * $t) / $x;
} else {
$this->H[$i+1][$n] = (-$s - $y * $t) / $z;
}
}
// Overflow control
$t = abs($this->H[$i][$n]);
if (($eps * $t) * $t > 1) {
for ($j = $i; $j <= $n; ++$j) {
$this->H[$j][$n] = $this->H[$j][$n] / $t;
}
}
}
}
// Complex vector
} elseif ($q < 0) {
$l = $n-1;
// Last vector component imaginary so matrix is triangular
if (abs($this->H[$n][$n-1]) > abs($this->H[$n-1][$n])) {
$this->H[$n-1][$n-1] = $q / $this->H[$n][$n-1];
$this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n-1];
} else {
$this->cdiv(0.0, -$this->H[$n-1][$n], $this->H[$n-1][$n-1] - $p, $q);
$this->H[$n-1][$n-1] = $this->cdivr;
$this->H[$n-1][$n] = $this->cdivi;
}
$this->H[$n][$n-1] = 0.0;
$this->H[$n][$n] = 1.0;
for ($i = $n-2; $i >= 0; --$i) {
// double ra,sa,vr,vi;
$ra = 0.0;
$sa = 0.0;
for ($j = $l; $j <= $n; ++$j) {
$ra = $ra + $this->H[$i][$j] * $this->H[$j][$n-1];
$sa = $sa + $this->H[$i][$j] * $this->H[$j][$n];
}
$w = $this->H[$i][$i] - $p;
if ($this->e[$i] < 0.0) {
$z = $w;
$r = $ra;
$s = $sa;
} else {
$l = $i;
if ($this->e[$i] == 0) {
$this->cdiv(-$ra, -$sa, $w, $q);
$this->H[$i][$n-1] = $this->cdivr;
$this->H[$i][$n] = $this->cdivi;
} else {
// Solve complex equations
$x = $this->H[$i][$i+1];
$y = $this->H[$i+1][$i];
$vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q;
$vi = ($this->d[$i] - $p) * 2.0 * $q;
if ($vr == 0.0 & $vi == 0.0) {
$vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z));
}
$this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi);
$this->H[$i][$n-1] = $this->cdivr;
$this->H[$i][$n] = $this->cdivi;
if (abs($x) > (abs($z) + abs($q))) {
$this->H[$i+1][$n-1] = (-$ra - $w * $this->H[$i][$n-1] + $q * $this->H[$i][$n]) / $x;
$this->H[$i+1][$n] = (-$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n-1]) / $x;
} else {
$this->cdiv(-$r - $y * $this->H[$i][$n-1], -$s - $y * $this->H[$i][$n], $z, $q);
$this->H[$i+1][$n-1] = $this->cdivr;
$this->H[$i+1][$n] = $this->cdivi;
}
}
// Overflow control
$t = max(abs($this->H[$i][$n-1]), abs($this->H[$i][$n]));
if (($eps * $t) * $t > 1) {
for ($j = $i; $j <= $n; ++$j) {
$this->H[$j][$n-1] = $this->H[$j][$n-1] / $t;
$this->H[$j][$n] = $this->H[$j][$n] / $t;
}
}
} // end else
} // end for
} // end else for complex case
} // end for
// Vectors of isolated roots
for ($i = 0; $i < $nn; ++$i) {
if ($i < $low | $i > $high) {
for ($j = $i; $j < $nn; ++$j) {
$this->V[$i][$j] = $this->H[$i][$j];
}
}
}
// Back transformation to get eigenvectors of original matrix
for ($j = $nn-1; $j >= $low; --$j) {
for ($i = $low; $i <= $high; ++$i) {
$z = 0.0;
for ($k = $low; $k <= min($j, $high); ++$k) {
$z = $z + $this->V[$i][$k] * $this->H[$k][$j];
}
$this->V[$i][$j] = $z;
}
}
} // end hqr2
/**
* Constructor: Check for symmetry, then construct the eigenvalue decomposition
*
* @access public
* @param A Square matrix
* @return Structure to access D and V.
*/
public function __construct($Arg)
{
$this->A = $Arg->getArray();
$this->n = $Arg->getColumnDimension();
$issymmetric = true;
for ($j = 0; ($j < $this->n) & $issymmetric; ++$j) {
for ($i = 0; ($i < $this->n) & $issymmetric; ++$i) {
$issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]);
}
}
if ($issymmetric) {
$this->V = $this->A;
// Tridiagonalize.
$this->tred2();
// Diagonalize.
$this->tql2();
} else {
$this->H = $this->A;
$this->ort = array();
// Reduce to Hessenberg form.
$this->orthes();
// Reduce Hessenberg to real Schur form.
$this->hqr2();
}
}
/**
* Return the eigenvector matrix
*
* @access public
* @return V
*/
public function getV()
{
return new Matrix($this->V, $this->n, $this->n);
}
/**
* Return the real parts of the eigenvalues
*
* @access public
* @return real(diag(D))
*/
public function getRealEigenvalues()
{
return $this->d;
}
/**
* Return the imaginary parts of the eigenvalues
*
* @access public
* @return imag(diag(D))
*/
public function getImagEigenvalues()
{
return $this->e;
}
/**
* Return the block diagonal eigenvalue matrix
*
* @access public
* @return D
*/
public function getD()
{
for ($i = 0; $i < $this->n; ++$i) {
$D[$i] = array_fill(0, $this->n, 0.0);
$D[$i][$i] = $this->d[$i];
if ($this->e[$i] == 0) {
continue;
}
$o = ($this->e[$i] > 0) ? $i + 1 : $i - 1;
$D[$i][$o] = $this->e[$i];
}
return new Matrix($D);
}
}

257
extend/PHPExcel/PHPExcel/Shared/JAMA/LUDecomposition.php

@ -0,0 +1,257 @@
<?php
/**
* @package JAMA
*
* For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
* unit lower triangular matrix L, an n-by-n upper triangular matrix U,
* and a permutation vector piv of length m so that A(piv,:) = L*U.
* If m < n, then L is m-by-m and U is m-by-n.
*
* The LU decompostion with pivoting always exists, even if the matrix is
* singular, so the constructor will never fail. The primary use of the
* LU decomposition is in the solution of square systems of simultaneous
* linear equations. This will fail if isNonsingular() returns false.
*
* @author Paul Meagher
* @author Bartosz Matosiuk
* @author Michael Bommarito
* @version 1.1
* @license PHP v3.0
*/
class PHPExcel_Shared_JAMA_LUDecomposition
{
const MATRIX_SINGULAR_EXCEPTION = "Can only perform operation on singular matrix.";
const MATRIX_SQUARE_EXCEPTION = "Mismatched Row dimension";
/**
* Decomposition storage
* @var array
*/
private $LU = array();
/**
* Row dimension.
* @var int
*/
private $m;
/**
* Column dimension.
* @var int
*/
private $n;
/**
* Pivot sign.
* @var int
*/
private $pivsign;
/**
* Internal storage of pivot vector.
* @var array
*/
private $piv = array();
/**
* LU Decomposition constructor.
*
* @param $A Rectangular matrix
* @return Structure to access L, U and piv.
*/
public function __construct($A)
{
if ($A instanceof PHPExcel_Shared_JAMA_Matrix) {
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
$this->LU = $A->getArray();
$this->m = $A->getRowDimension();
$this->n = $A->getColumnDimension();
for ($i = 0; $i < $this->m; ++$i) {
$this->piv[$i] = $i;
}
$this->pivsign = 1;
$LUrowi = $LUcolj = array();
// Outer loop.
for ($j = 0; $j < $this->n; ++$j) {
// Make a copy of the j-th column to localize references.
for ($i = 0; $i < $this->m; ++$i) {
$LUcolj[$i] = &$this->LU[$i][$j];
}
// Apply previous transformations.
for ($i = 0; $i < $this->m; ++$i) {
$LUrowi = $this->LU[$i];
// Most of the time is spent in the following dot product.
$kmax = min($i, $j);
$s = 0.0;
for ($k = 0; $k < $kmax; ++$k) {
$s += $LUrowi[$k] * $LUcolj[$k];
}
$LUrowi[$j] = $LUcolj[$i] -= $s;
}
// Find pivot and exchange if necessary.
$p = $j;
for ($i = $j+1; $i < $this->m; ++$i) {
if (abs($LUcolj[$i]) > abs($LUcolj[$p])) {
$p = $i;
}
}
if ($p != $j) {
for ($k = 0; $k < $this->n; ++$k) {
$t = $this->LU[$p][$k];
$this->LU[$p][$k] = $this->LU[$j][$k];
$this->LU[$j][$k] = $t;
}
$k = $this->piv[$p];
$this->piv[$p] = $this->piv[$j];
$this->piv[$j] = $k;
$this->pivsign = $this->pivsign * -1;
}
// Compute multipliers.
if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) {
for ($i = $j+1; $i < $this->m; ++$i) {
$this->LU[$i][$j] /= $this->LU[$j][$j];
}
}
}
} else {
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ARGUMENT_TYPE_EXCEPTION);
}
} // function __construct()
/**
* Get lower triangular factor.
*
* @return array Lower triangular factor
*/
public function getL()
{
for ($i = 0; $i < $this->m; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i > $j) {
$L[$i][$j] = $this->LU[$i][$j];
} elseif ($i == $j) {
$L[$i][$j] = 1.0;
} else {
$L[$i][$j] = 0.0;
}
}
}
return new PHPExcel_Shared_JAMA_Matrix($L);
} // function getL()
/**
* Get upper triangular factor.
*
* @return array Upper triangular factor
*/
public function getU()
{
for ($i = 0; $i < $this->n; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i <= $j) {
$U[$i][$j] = $this->LU[$i][$j];
} else {
$U[$i][$j] = 0.0;
}
}
}
return new PHPExcel_Shared_JAMA_Matrix($U);
} // function getU()
/**
* Return pivot permutation vector.
*
* @return array Pivot vector
*/
public function getPivot()
{
return $this->piv;
} // function getPivot()
/**
* Alias for getPivot
*
* @see getPivot
*/
public function getDoublePivot()
{
return $this->getPivot();
} // function getDoublePivot()
/**
* Is the matrix nonsingular?
*
* @return true if U, and hence A, is nonsingular.
*/
public function isNonsingular()
{
for ($j = 0; $j < $this->n; ++$j) {
if ($this->LU[$j][$j] == 0) {
return false;
}
}
return true;
} // function isNonsingular()
/**
* Count determinants
*
* @return array d matrix deterninat
*/
public function det()
{
if ($this->m == $this->n) {
$d = $this->pivsign;
for ($j = 0; $j < $this->n; ++$j) {
$d *= $this->LU[$j][$j];
}
return $d;
} else {
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MATRIX_DIMENSION_EXCEPTION);
}
} // function det()
/**
* Solve A*X = B
*
* @param $B A Matrix with as many rows as A and any number of columns.
* @return X so that L*U*X = B(piv,:)
* @PHPExcel_Calculation_Exception IllegalArgumentException Matrix row dimensions must agree.
* @PHPExcel_Calculation_Exception RuntimeException Matrix is singular.
*/
public function solve($B)
{
if ($B->getRowDimension() == $this->m) {
if ($this->isNonsingular()) {
// Copy right hand side with pivoting
$nx = $B->getColumnDimension();
$X = $B->getMatrix($this->piv, 0, $nx-1);
// Solve L*Y = B(piv,:)
for ($k = 0; $k < $this->n; ++$k) {
for ($i = $k+1; $i < $this->n; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
}
}
}
// Solve U*X = Y;
for ($k = $this->n-1; $k >= 0; --$k) {
for ($j = 0; $j < $nx; ++$j) {
$X->A[$k][$j] /= $this->LU[$k][$k];
}
for ($i = 0; $i < $k; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
}
}
}
return $X;
} else {
throw new PHPExcel_Calculation_Exception(self::MATRIX_SINGULAR_EXCEPTION);
}
} else {
throw new PHPExcel_Calculation_Exception(self::MATRIX_SQUARE_EXCEPTION);
}
}
}

1159
extend/PHPExcel/PHPExcel/Shared/JAMA/Matrix.php

File diff suppressed because it is too large

235
extend/PHPExcel/PHPExcel/Shared/JAMA/QRDecomposition.php

@ -0,0 +1,235 @@
<?php
/**
* @package JAMA
*
* For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
* orthogonal matrix Q and an n-by-n upper triangular matrix R so that
* A = Q*R.
*
* The QR decompostion always exists, even if the matrix does not have
* full rank, so the constructor will never fail. The primary use of the
* QR decomposition is in the least squares solution of nonsquare systems
* of simultaneous linear equations. This will fail if isFullRank()
* returns false.
*
* @author Paul Meagher
* @license PHP v3.0
* @version 1.1
*/
class PHPExcel_Shared_JAMA_QRDecomposition
{
const MATRIX_RANK_EXCEPTION = "Can only perform operation on full-rank matrix.";
/**
* Array for internal storage of decomposition.
* @var array
*/
private $QR = array();
/**
* Row dimension.
* @var integer
*/
private $m;
/**
* Column dimension.
* @var integer
*/
private $n;
/**
* Array for internal storage of diagonal of R.
* @var array
*/
private $Rdiag = array();
/**
* QR Decomposition computed by Householder reflections.
*
* @param matrix $A Rectangular matrix
* @return Structure to access R and the Householder vectors and compute Q.
*/
public function __construct($A)
{
if ($A instanceof PHPExcel_Shared_JAMA_Matrix) {
// Initialize.
$this->QR = $A->getArrayCopy();
$this->m = $A->getRowDimension();
$this->n = $A->getColumnDimension();
// Main loop.
for ($k = 0; $k < $this->n; ++$k) {
// Compute 2-norm of k-th column without under/overflow.
$nrm = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$nrm = hypo($nrm, $this->QR[$i][$k]);
}
if ($nrm != 0.0) {
// Form k-th Householder vector.
if ($this->QR[$k][$k] < 0) {
$nrm = -$nrm;
}
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$k] /= $nrm;
}
$this->QR[$k][$k] += 1.0;
// Apply transformation to remaining columns.
for ($j = $k+1; $j < $this->n; ++$j) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $this->QR[$i][$j];
}
$s = -$s/$this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
$this->Rdiag[$k] = -$nrm;
}
} else {
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ARGUMENT_TYPE_EXCEPTION);
}
} // function __construct()
/**
* Is the matrix full rank?
*
* @return boolean true if R, and hence A, has full rank, else false.
*/
public function isFullRank()
{
for ($j = 0; $j < $this->n; ++$j) {
if ($this->Rdiag[$j] == 0) {
return false;
}
}
return true;
} // function isFullRank()
/**
* Return the Householder vectors
*
* @return Matrix Lower trapezoidal matrix whose columns define the reflections
*/
public function getH()
{
for ($i = 0; $i < $this->m; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i >= $j) {
$H[$i][$j] = $this->QR[$i][$j];
} else {
$H[$i][$j] = 0.0;
}
}
}
return new PHPExcel_Shared_JAMA_Matrix($H);
} // function getH()
/**
* Return the upper triangular factor
*
* @return Matrix upper triangular factor
*/
public function getR()
{
for ($i = 0; $i < $this->n; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i < $j) {
$R[$i][$j] = $this->QR[$i][$j];
} elseif ($i == $j) {
$R[$i][$j] = $this->Rdiag[$i];
} else {
$R[$i][$j] = 0.0;
}
}
}
return new PHPExcel_Shared_JAMA_Matrix($R);
} // function getR()
/**
* Generate and return the (economy-sized) orthogonal factor
*
* @return Matrix orthogonal factor
*/
public function getQ()
{
for ($k = $this->n-1; $k >= 0; --$k) {
for ($i = 0; $i < $this->m; ++$i) {
$Q[$i][$k] = 0.0;
}
$Q[$k][$k] = 1.0;
for ($j = $k; $j < $this->n; ++$j) {
if ($this->QR[$k][$k] != 0) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $Q[$i][$j];
}
$s = -$s/$this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$Q[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
}
/*
for($i = 0; $i < count($Q); ++$i) {
for($j = 0; $j < count($Q); ++$j) {
if (! isset($Q[$i][$j]) ) {
$Q[$i][$j] = 0;
}
}
}
*/
return new PHPExcel_Shared_JAMA_Matrix($Q);
} // function getQ()
/**
* Least squares solution of A*X = B
*
* @param Matrix $B A Matrix with as many rows as A and any number of columns.
* @return Matrix Matrix that minimizes the two norm of Q*R*X-B.
*/
public function solve($B)
{
if ($B->getRowDimension() == $this->m) {
if ($this->isFullRank()) {
// Copy right hand side
$nx = $B->getColumnDimension();
$X = $B->getArrayCopy();
// Compute Y = transpose(Q)*B
for ($k = 0; $k < $this->n; ++$k) {
for ($j = 0; $j < $nx; ++$j) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $X[$i][$j];
}
$s = -$s/$this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$X[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
// Solve R*X = Y;
for ($k = $this->n-1; $k >= 0; --$k) {
for ($j = 0; $j < $nx; ++$j) {
$X[$k][$j] /= $this->Rdiag[$k];
}
for ($i = 0; $i < $k; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k];
}
}
}
$X = new PHPExcel_Shared_JAMA_Matrix($X);
return ($X->getMatrix(0, $this->n-1, 0, $nx));
} else {
throw new PHPExcel_Calculation_Exception(self::MATRIX_RANK_EXCEPTION);
}
} else {
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MATRIX_DIMENSION_EXCEPTION);
}
}
}

528
extend/PHPExcel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php

@ -0,0 +1,528 @@
<?php
/**
* @package JAMA
*
* For an m-by-n matrix A with m >= n, the singular value decomposition is
* an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and
* an n-by-n orthogonal matrix V so that A = U*S*V'.
*
* The singular values, sigma[$k] = S[$k][$k], are ordered so that
* sigma[0] >= sigma[1] >= ... >= sigma[n-1].
*
* The singular value decompostion always exists, so the constructor will
* never fail. The matrix condition number and the effective numerical
* rank can be computed from this decomposition.
*
* @author Paul Meagher
* @license PHP v3.0
* @version 1.1
*/
class SingularValueDecomposition
{
/**
* Internal storage of U.
* @var array
*/
private $U = array();
/**
* Internal storage of V.
* @var array
*/
private $V = array();
/**
* Internal storage of singular values.
* @var array
*/
private $s = array();
/**
* Row dimension.
* @var int
*/
private $m;
/**
* Column dimension.
* @var int
*/
private $n;
/**
* Construct the singular value decomposition
*
* Derived from LINPACK code.
*
* @param $A Rectangular matrix
* @return Structure to access U, S and V.
*/
public function __construct($Arg)
{
// Initialize.
$A = $Arg->getArrayCopy();
$this->m = $Arg->getRowDimension();
$this->n = $Arg->getColumnDimension();
$nu = min($this->m, $this->n);
$e = array();
$work = array();
$wantu = true;
$wantv = true;
$nct = min($this->m - 1, $this->n);
$nrt = max(0, min($this->n - 2, $this->m));
// Reduce A to bidiagonal form, storing the diagonal elements
// in s and the super-diagonal elements in e.
for ($k = 0; $k < max($nct, $nrt); ++$k) {
if ($k < $nct) {
// Compute the transformation for the k-th column and
// place the k-th diagonal in s[$k].
// Compute 2-norm of k-th column without under/overflow.
$this->s[$k] = 0;
for ($i = $k; $i < $this->m; ++$i) {
$this->s[$k] = hypo($this->s[$k], $A[$i][$k]);
}
if ($this->s[$k] != 0.0) {
if ($A[$k][$k] < 0.0) {
$this->s[$k] = -$this->s[$k];
}
for ($i = $k; $i < $this->m; ++$i) {
$A[$i][$k] /= $this->s[$k];
}
$A[$k][$k] += 1.0;
}
$this->s[$k] = -$this->s[$k];
}
for ($j = $k + 1; $j < $this->n; ++$j) {
if (($k < $nct) & ($this->s[$k] != 0.0)) {
// Apply the transformation.
$t = 0;
for ($i = $k; $i < $this->m; ++$i) {
$t += $A[$i][$k] * $A[$i][$j];
}
$t = -$t / $A[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$A[$i][$j] += $t * $A[$i][$k];
}
// Place the k-th row of A into e for the
// subsequent calculation of the row transformation.
$e[$j] = $A[$k][$j];
}
}
if ($wantu and ($k < $nct)) {
// Place the transformation in U for subsequent back
// multiplication.
for ($i = $k; $i < $this->m; ++$i) {
$this->U[$i][$k] = $A[$i][$k];
}
}
if ($k < $nrt) {
// Compute the k-th row transformation and place the
// k-th super-diagonal in e[$k].
// Compute 2-norm without under/overflow.
$e[$k] = 0;
for ($i = $k + 1; $i < $this->n; ++$i) {
$e[$k] = hypo($e[$k], $e[$i]);
}
if ($e[$k] != 0.0) {
if ($e[$k+1] < 0.0) {
$e[$k] = -$e[$k];
}
for ($i = $k + 1; $i < $this->n; ++$i) {
$e[$i] /= $e[$k];
}
$e[$k+1] += 1.0;
}
$e[$k] = -$e[$k];
if (($k+1 < $this->m) and ($e[$k] != 0.0)) {
// Apply the transformation.
for ($i = $k+1; $i < $this->m; ++$i) {
$work[$i] = 0.0;
}
for ($j = $k+1; $j < $this->n; ++$j) {
for ($i = $k+1; $i < $this->m; ++$i) {
$work[$i] += $e[$j] * $A[$i][$j];
}
}
for ($j = $k + 1; $j < $this->n; ++$j) {
$t = -$e[$j] / $e[$k+1];
for ($i = $k + 1; $i < $this->m; ++$i) {
$A[$i][$j] += $t * $work[$i];
}
}
}
if ($wantv) {
// Place the transformation in V for subsequent
// back multiplication.
for ($i = $k + 1; $i < $this->n; ++$i) {
$this->V[$i][$k] = $e[$i];
}
}
}
}
// Set up the final bidiagonal matrix or order p.
$p = min($this->n, $this->m + 1);
if ($nct < $this->n) {
$this->s[$nct] = $A[$nct][$nct];
}
if ($this->m < $p) {
$this->s[$p-1] = 0.0;
}
if ($nrt + 1 < $p) {
$e[$nrt] = $A[$nrt][$p-1];
}
$e[$p-1] = 0.0;
// If required, generate U.
if ($wantu) {
for ($j = $nct; $j < $nu; ++$j) {
for ($i = 0; $i < $this->m; ++$i) {
$this->U[$i][$j] = 0.0;
}
$this->U[$j][$j] = 1.0;
}
for ($k = $nct - 1; $k >= 0; --$k) {
if ($this->s[$k] != 0.0) {
for ($j = $k + 1; $j < $nu; ++$j) {
$t = 0;
for ($i = $k; $i < $this->m; ++$i) {
$t += $this->U[$i][$k] * $this->U[$i][$j];
}
$t = -$t / $this->U[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$this->U[$i][$j] += $t * $this->U[$i][$k];
}
}
for ($i = $k; $i < $this->m; ++$i) {
$this->U[$i][$k] = -$this->U[$i][$k];
}
$this->U[$k][$k] = 1.0 + $this->U[$k][$k];
for ($i = 0; $i < $k - 1; ++$i) {
$this->U[$i][$k] = 0.0;
}
} else {
for ($i = 0; $i < $this->m; ++$i) {
$this->U[$i][$k] = 0.0;
}
$this->U[$k][$k] = 1.0;
}
}
}
// If required, generate V.
if ($wantv) {
for ($k = $this->n - 1; $k >= 0; --$k) {
if (($k < $nrt) and ($e[$k] != 0.0)) {
for ($j = $k + 1; $j < $nu; ++$j) {
$t = 0;
for ($i = $k + 1; $i < $this->n; ++$i) {
$t += $this->V[$i][$k]* $this->V[$i][$j];
}
$t = -$t / $this->V[$k+1][$k];
for ($i = $k + 1; $i < $this->n; ++$i) {
$this->V[$i][$j] += $t * $this->V[$i][$k];
}
}
}
for ($i = 0; $i < $this->n; ++$i) {
$this->V[$i][$k] = 0.0;
}
$this->V[$k][$k] = 1.0;
}
}
// Main iteration loop for the singular values.
$pp = $p - 1;
$iter = 0;
$eps = pow(2.0, -52.0);
while ($p > 0) {
// Here is where a test for too many iterations would go.
// This section of the program inspects for negligible
// elements in the s and e arrays. On completion the
// variables kase and k are set as follows:
// kase = 1 if s(p) and e[k-1] are negligible and k<p
// kase = 2 if s(k) is negligible and k<p
// kase = 3 if e[k-1] is negligible, k<p, and
// s(k), ..., s(p) are not negligible (qr step).
// kase = 4 if e(p-1) is negligible (convergence).
for ($k = $p - 2; $k >= -1; --$k) {
if ($k == -1) {
break;
}
if (abs($e[$k]) <= $eps * (abs($this->s[$k]) + abs($this->s[$k+1]))) {
$e[$k] = 0.0;
break;
}
}
if ($k == $p - 2) {
$kase = 4;
} else {
for ($ks = $p - 1; $ks >= $k; --$ks) {
if ($ks == $k) {
break;
}
$t = ($ks != $p ? abs($e[$ks]) : 0.) + ($ks != $k + 1 ? abs($e[$ks-1]) : 0.);
if (abs($this->s[$ks]) <= $eps * $t) {
$this->s[$ks] = 0.0;
break;
}
}
if ($ks == $k) {
$kase = 3;
} elseif ($ks == $p-1) {
$kase = 1;
} else {
$kase = 2;
$k = $ks;
}
}
++$k;
// Perform the task indicated by kase.
switch ($kase) {
// Deflate negligible s(p).
case 1:
$f = $e[$p-2];
$e[$p-2] = 0.0;
for ($j = $p - 2; $j >= $k; --$j) {
$t = hypo($this->s[$j], $f);
$cs = $this->s[$j] / $t;
$sn = $f / $t;
$this->s[$j] = $t;
if ($j != $k) {
$f = -$sn * $e[$j-1];
$e[$j-1] = $cs * $e[$j-1];
}
if ($wantv) {
for ($i = 0; $i < $this->n; ++$i) {
$t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$p-1];
$this->V[$i][$p-1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$p-1];
$this->V[$i][$j] = $t;
}
}
}
break;
// Split at negligible s(k).
case 2:
$f = $e[$k-1];
$e[$k-1] = 0.0;
for ($j = $k; $j < $p; ++$j) {
$t = hypo($this->s[$j], $f);
$cs = $this->s[$j] / $t;
$sn = $f / $t;
$this->s[$j] = $t;
$f = -$sn * $e[$j];
$e[$j] = $cs * $e[$j];
if ($wantu) {
for ($i = 0; $i < $this->m; ++$i) {
$t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$k-1];
$this->U[$i][$k-1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$k-1];
$this->U[$i][$j] = $t;
}
}
}
break;
// Perform one qr step.
case 3:
// Calculate the shift.
$scale = max(max(max(max(abs($this->s[$p-1]), abs($this->s[$p-2])), abs($e[$p-2])), abs($this->s[$k])), abs($e[$k]));
$sp = $this->s[$p-1] / $scale;
$spm1 = $this->s[$p-2] / $scale;
$epm1 = $e[$p-2] / $scale;
$sk = $this->s[$k] / $scale;
$ek = $e[$k] / $scale;
$b = (($spm1 + $sp) * ($spm1 - $sp) + $epm1 * $epm1) / 2.0;
$c = ($sp * $epm1) * ($sp * $epm1);
$shift = 0.0;
if (($b != 0.0) || ($c != 0.0)) {
$shift = sqrt($b * $b + $c);
if ($b < 0.0) {
$shift = -$shift;
}
$shift = $c / ($b + $shift);
}
$f = ($sk + $sp) * ($sk - $sp) + $shift;
$g = $sk * $ek;
// Chase zeros.
for ($j = $k; $j < $p-1; ++$j) {
$t = hypo($f, $g);
$cs = $f/$t;
$sn = $g/$t;
if ($j != $k) {
$e[$j-1] = $t;
}
$f = $cs * $this->s[$j] + $sn * $e[$j];
$e[$j] = $cs * $e[$j] - $sn * $this->s[$j];
$g = $sn * $this->s[$j+1];
$this->s[$j+1] = $cs * $this->s[$j+1];
if ($wantv) {
for ($i = 0; $i < $this->n; ++$i) {
$t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$j+1];
$this->V[$i][$j+1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$j+1];
$this->V[$i][$j] = $t;
}
}
$t = hypo($f, $g);
$cs = $f/$t;
$sn = $g/$t;
$this->s[$j] = $t;
$f = $cs * $e[$j] + $sn * $this->s[$j+1];
$this->s[$j+1] = -$sn * $e[$j] + $cs * $this->s[$j+1];
$g = $sn * $e[$j+1];
$e[$j+1] = $cs * $e[$j+1];
if ($wantu && ($j < $this->m - 1)) {
for ($i = 0; $i < $this->m; ++$i) {
$t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$j+1];
$this->U[$i][$j+1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$j+1];
$this->U[$i][$j] = $t;
}
}
}
$e[$p-2] = $f;
$iter = $iter + 1;
break;
// Convergence.
case 4:
// Make the singular values positive.
if ($this->s[$k] <= 0.0) {
$this->s[$k] = ($this->s[$k] < 0.0 ? -$this->s[$k] : 0.0);
if ($wantv) {
for ($i = 0; $i <= $pp; ++$i) {
$this->V[$i][$k] = -$this->V[$i][$k];
}
}
}
// Order the singular values.
while ($k < $pp) {
if ($this->s[$k] >= $this->s[$k+1]) {
break;
}
$t = $this->s[$k];
$this->s[$k] = $this->s[$k+1];
$this->s[$k+1] = $t;
if ($wantv and ($k < $this->n - 1)) {
for ($i = 0; $i < $this->n; ++$i) {
$t = $this->V[$i][$k+1];
$this->V[$i][$k+1] = $this->V[$i][$k];
$this->V[$i][$k] = $t;
}
}
if ($wantu and ($k < $this->m-1)) {
for ($i = 0; $i < $this->m; ++$i) {
$t = $this->U[$i][$k+1];
$this->U[$i][$k+1] = $this->U[$i][$k];
$this->U[$i][$k] = $t;
}
}
++$k;
}
$iter = 0;
--$p;
break;
} // end switch
} // end while
} // end constructor
/**
* Return the left singular vectors
*
* @access public
* @return U
*/
public function getU()
{
return new Matrix($this->U, $this->m, min($this->m + 1, $this->n));
}
/**
* Return the right singular vectors
*
* @access public
* @return V
*/
public function getV()
{
return new Matrix($this->V);
}
/**
* Return the one-dimensional array of singular values
*
* @access public
* @return diagonal of S.
*/
public function getSingularValues()
{
return $this->s;
}
/**
* Return the diagonal matrix of singular values
*
* @access public
* @return S
*/
public function getS()
{
for ($i = 0; $i < $this->n; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
$S[$i][$j] = 0.0;
}
$S[$i][$i] = $this->s[$i];
}
return new Matrix($S);
}
/**
* Two norm
*
* @access public
* @return max(S)
*/
public function norm2()
{
return $this->s[0];
}
/**
* Two norm condition number
*
* @access public
* @return max(S)/min(S)
*/
public function cond()
{
return $this->s[0] / $this->s[min($this->m, $this->n) - 1];
}
/**
* Effective numerical matrix rank
*
* @access public
* @return Number of nonnegligible singular values.
*/
public function rank()
{
$eps = pow(2.0, -52.0);
$tol = max($this->m, $this->n) * $this->s[0] * $eps;
$r = 0;
for ($i = 0; $i < count($this->s); ++$i) {
if ($this->s[$i] > $tol) {
++$r;
}
}
return $r;
}
}

83
extend/PHPExcel/PHPExcel/Shared/JAMA/utils/Error.php

@ -0,0 +1,83 @@
<?php
/**
* @package JAMA
*
* Error handling
* @author Michael Bommarito
* @version 01292005
*/
//Language constant
define('JAMALANG', 'EN');
//All errors may be defined by the following format:
//define('ExceptionName', N);
//$error['lang'][ExceptionName] = 'Error message';
$error = array();
/*
I've used Babelfish and a little poor knowledge of Romance/Germanic languages for the translations here.
Feel free to correct anything that looks amiss to you.
*/
define('POLYMORPHIC_ARGUMENT_EXCEPTION', -1);
$error['EN'][POLYMORPHIC_ARGUMENT_EXCEPTION] = "Invalid argument pattern for polymorphic function.";
$error['FR'][POLYMORPHIC_ARGUMENT_EXCEPTION] = "Modèle inadmissible d'argument pour la fonction polymorphe.".
$error['DE'][POLYMORPHIC_ARGUMENT_EXCEPTION] = "Unzulässiges Argumentmuster für polymorphe Funktion.";
define('ARGUMENT_TYPE_EXCEPTION', -2);
$error['EN'][ARGUMENT_TYPE_EXCEPTION] = "Invalid argument type.";
$error['FR'][ARGUMENT_TYPE_EXCEPTION] = "Type inadmissible d'argument.";
$error['DE'][ARGUMENT_TYPE_EXCEPTION] = "Unzulässige Argumentart.";
define('ARGUMENT_BOUNDS_EXCEPTION', -3);
$error['EN'][ARGUMENT_BOUNDS_EXCEPTION] = "Invalid argument range.";
$error['FR'][ARGUMENT_BOUNDS_EXCEPTION] = "Gamme inadmissible d'argument.";
$error['DE'][ARGUMENT_BOUNDS_EXCEPTION] = "Unzulässige Argumentstrecke.";
define('MATRIX_DIMENSION_EXCEPTION', -4);
$error['EN'][MATRIX_DIMENSION_EXCEPTION] = "Matrix dimensions are not equal.";
$error['FR'][MATRIX_DIMENSION_EXCEPTION] = "Les dimensions de Matrix ne sont pas égales.";
$error['DE'][MATRIX_DIMENSION_EXCEPTION] = "Matrixmaße sind nicht gleich.";
define('PRECISION_LOSS_EXCEPTION', -5);
$error['EN'][PRECISION_LOSS_EXCEPTION] = "Significant precision loss detected.";
$error['FR'][PRECISION_LOSS_EXCEPTION] = "Perte significative de précision détectée.";
$error['DE'][PRECISION_LOSS_EXCEPTION] = "Bedeutender Präzision Verlust ermittelte.";
define('MATRIX_SPD_EXCEPTION', -6);
$error['EN'][MATRIX_SPD_EXCEPTION] = "Can only perform operation on symmetric positive definite matrix.";
$error['FR'][MATRIX_SPD_EXCEPTION] = "Perte significative de précision détectée.";
$error['DE'][MATRIX_SPD_EXCEPTION] = "Bedeutender Präzision Verlust ermittelte.";
define('MATRIX_SINGULAR_EXCEPTION', -7);
$error['EN'][MATRIX_SINGULAR_EXCEPTION] = "Can only perform operation on singular matrix.";
define('MATRIX_RANK_EXCEPTION', -8);
$error['EN'][MATRIX_RANK_EXCEPTION] = "Can only perform operation on full-rank matrix.";
define('ARRAY_LENGTH_EXCEPTION', -9);
$error['EN'][ARRAY_LENGTH_EXCEPTION] = "Array length must be a multiple of m.";
define('ROW_LENGTH_EXCEPTION', -10);
$error['EN'][ROW_LENGTH_EXCEPTION] = "All rows must have the same length.";
/**
* Custom error handler
* @param int $num Error number
*/
function JAMAError($errorNumber = null)
{
global $error;
if (isset($errorNumber)) {
if (isset($error[JAMALANG][$errorNumber])) {
return $error[JAMALANG][$errorNumber];
} else {
return $error['EN'][$errorNumber];
}
} else {
return ("Invalid argument to JAMAError()");
}
}

44
extend/PHPExcel/PHPExcel/Shared/JAMA/utils/Maths.php

@ -0,0 +1,44 @@
<?php
/**
* @package JAMA
*
* Pythagorean Theorem:
*
* a = 3
* b = 4
* r = sqrt(square(a) + square(b))
* r = 5
*
* r = sqrt(a^2 + b^2) without under/overflow.
*/
function hypo($a, $b)
{
if (abs($a) > abs($b)) {
$r = $b / $a;
$r = abs($a) * sqrt(1 + $r * $r);
} elseif ($b != 0) {
$r = $a / $b;
$r = abs($b) * sqrt(1 + $r * $r);
} else {
$r = 0.0;
}
return $r;
} // function hypo()
/**
* Mike Bommarito's version.
* Compute n-dimensional hyotheneuse.
*
function hypot() {
$s = 0;
foreach (func_get_args() as $d) {
if (is_numeric($d)) {
$s += pow($d, 2);
} else {
throw new PHPExcel_Calculation_Exception(JAMAError(ARGUMENT_TYPE_EXCEPTION));
}
}
return sqrt($s);
}
*/

526
extend/PHPExcel/PHPExcel/Shared/OLE.php

@ -0,0 +1,526 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id: OLE.php,v 1.13 2007/03/07 14:38:25 schmidt Exp $
/**
* Array for storing OLE instances that are accessed from
* OLE_ChainedBlockStream::stream_open().
* @var array
*/
$GLOBALS['_OLE_INSTANCES'] = array();
/**
* OLE package base class.
*
* @author Xavier Noguer <xnoguer@php.net>
* @author Christian Schmidt <schmidt@php.net>
* @category PHPExcel
* @package PHPExcel_Shared_OLE
*/
class PHPExcel_Shared_OLE
{
const OLE_PPS_TYPE_ROOT = 5;
const OLE_PPS_TYPE_DIR = 1;
const OLE_PPS_TYPE_FILE = 2;
const OLE_DATA_SIZE_SMALL = 0x1000;
const OLE_LONG_INT_SIZE = 4;
const OLE_PPS_SIZE = 0x80;
/**
* The file handle for reading an OLE container
* @var resource
*/
public $_file_handle;
/**
* Array of PPS's found on the OLE container
* @var array
*/
public $_list = array();
/**
* Root directory of OLE container
* @var OLE_PPS_Root
*/
public $root;
/**
* Big Block Allocation Table
* @var array (blockId => nextBlockId)
*/
public $bbat;
/**
* Short Block Allocation Table
* @var array (blockId => nextBlockId)
*/
public $sbat;
/**
* Size of big blocks. This is usually 512.
* @var int number of octets per block.
*/
public $bigBlockSize;
/**
* Size of small blocks. This is usually 64.
* @var int number of octets per block
*/
public $smallBlockSize;
/**
* Reads an OLE container from the contents of the file given.
*
* @acces public
* @param string $file
* @return mixed true on success, PEAR_Error on failure
*/
public function read($file)
{
$fh = fopen($file, "r");
if (!$fh) {
throw new PHPExcel_Reader_Exception("Can't open file $file");
}
$this->_file_handle = $fh;
$signature = fread($fh, 8);
if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) {
throw new PHPExcel_Reader_Exception("File doesn't seem to be an OLE container.");
}
fseek($fh, 28);
if (fread($fh, 2) != "\xFE\xFF") {
// This shouldn't be a problem in practice
throw new PHPExcel_Reader_Exception("Only Little-Endian encoding is supported.");
}
// Size of blocks and short blocks in bytes
$this->bigBlockSize = pow(2, self::_readInt2($fh));
$this->smallBlockSize = pow(2, self::_readInt2($fh));
// Skip UID, revision number and version number
fseek($fh, 44);
// Number of blocks in Big Block Allocation Table
$bbatBlockCount = self::_readInt4($fh);
// Root chain 1st block
$directoryFirstBlockId = self::_readInt4($fh);
// Skip unused bytes
fseek($fh, 56);
// Streams shorter than this are stored using small blocks
$this->bigBlockThreshold = self::_readInt4($fh);
// Block id of first sector in Short Block Allocation Table
$sbatFirstBlockId = self::_readInt4($fh);
// Number of blocks in Short Block Allocation Table
$sbbatBlockCount = self::_readInt4($fh);
// Block id of first sector in Master Block Allocation Table
$mbatFirstBlockId = self::_readInt4($fh);
// Number of blocks in Master Block Allocation Table
$mbbatBlockCount = self::_readInt4($fh);
$this->bbat = array();
// Remaining 4 * 109 bytes of current block is beginning of Master
// Block Allocation Table
$mbatBlocks = array();
for ($i = 0; $i < 109; ++$i) {
$mbatBlocks[] = self::_readInt4($fh);
}
// Read rest of Master Block Allocation Table (if any is left)
$pos = $this->_getBlockOffset($mbatFirstBlockId);
for ($i = 0; $i < $mbbatBlockCount; ++$i) {
fseek($fh, $pos);
for ($j = 0; $j < $this->bigBlockSize / 4 - 1; ++$j) {
$mbatBlocks[] = self::_readInt4($fh);
}
// Last block id in each block points to next block
$pos = $this->_getBlockOffset(self::_readInt4($fh));
}
// Read Big Block Allocation Table according to chain specified by
// $mbatBlocks
for ($i = 0; $i < $bbatBlockCount; ++$i) {
$pos = $this->_getBlockOffset($mbatBlocks[$i]);
fseek($fh, $pos);
for ($j = 0; $j < $this->bigBlockSize / 4; ++$j) {
$this->bbat[] = self::_readInt4($fh);
}
}
// Read short block allocation table (SBAT)
$this->sbat = array();
$shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4;
$sbatFh = $this->getStream($sbatFirstBlockId);
for ($blockId = 0; $blockId < $shortBlockCount; ++$blockId) {
$this->sbat[$blockId] = self::_readInt4($sbatFh);
}
fclose($sbatFh);
$this->_readPpsWks($directoryFirstBlockId);
return true;
}
/**
* @param int block id
* @param int byte offset from beginning of file
* @access public
*/
public function _getBlockOffset($blockId)
{
return 512 + $blockId * $this->bigBlockSize;
}
/**
* Returns a stream for use with fread() etc. External callers should
* use PHPExcel_Shared_OLE_PPS_File::getStream().
* @param int|PPS block id or PPS
* @return resource read-only stream
*/
public function getStream($blockIdOrPps)
{
static $isRegistered = false;
if (!$isRegistered) {
stream_wrapper_register('ole-chainedblockstream', 'PHPExcel_Shared_OLE_ChainedBlockStream');
$isRegistered = true;
}
// Store current instance in global array, so that it can be accessed
// in OLE_ChainedBlockStream::stream_open().
// Object is removed from self::$instances in OLE_Stream::close().
$GLOBALS['_OLE_INSTANCES'][] = $this;
$instanceId = end(array_keys($GLOBALS['_OLE_INSTANCES']));
$path = 'ole-chainedblockstream://oleInstanceId=' . $instanceId;
if ($blockIdOrPps instanceof PHPExcel_Shared_OLE_PPS) {
$path .= '&blockId=' . $blockIdOrPps->_StartBlock;
$path .= '&size=' . $blockIdOrPps->Size;
} else {
$path .= '&blockId=' . $blockIdOrPps;
}
return fopen($path, 'r');
}
/**
* Reads a signed char.
* @param resource file handle
* @return int
* @access public
*/
private static function _readInt1($fh)
{
list(, $tmp) = unpack("c", fread($fh, 1));
return $tmp;
}
/**
* Reads an unsigned short (2 octets).
* @param resource file handle
* @return int
* @access public
*/
private static function _readInt2($fh)
{
list(, $tmp) = unpack("v", fread($fh, 2));
return $tmp;
}
/**
* Reads an unsigned long (4 octets).
* @param resource file handle
* @return int
* @access public
*/
private static function _readInt4($fh)
{
list(, $tmp) = unpack("V", fread($fh, 4));
return $tmp;
}
/**
* Gets information about all PPS's on the OLE container from the PPS WK's
* creates an OLE_PPS object for each one.
*
* @access public
* @param integer the block id of the first block
* @return mixed true on success, PEAR_Error on failure
*/
public function _readPpsWks($blockId)
{
$fh = $this->getStream($blockId);
for ($pos = 0;; $pos += 128) {
fseek($fh, $pos, SEEK_SET);
$nameUtf16 = fread($fh, 64);
$nameLength = self::_readInt2($fh);
$nameUtf16 = substr($nameUtf16, 0, $nameLength - 2);
// Simple conversion from UTF-16LE to ISO-8859-1
$name = str_replace("\x00", "", $nameUtf16);
$type = self::_readInt1($fh);
switch ($type) {
case self::OLE_PPS_TYPE_ROOT:
$pps = new PHPExcel_Shared_OLE_PPS_Root(null, null, array());
$this->root = $pps;
break;
case self::OLE_PPS_TYPE_DIR:
$pps = new PHPExcel_Shared_OLE_PPS(null, null, null, null, null, null, null, null, null, array());
break;
case self::OLE_PPS_TYPE_FILE:
$pps = new PHPExcel_Shared_OLE_PPS_File($name);
break;
default:
continue;
}
fseek($fh, 1, SEEK_CUR);
$pps->Type = $type;
$pps->Name = $name;
$pps->PrevPps = self::_readInt4($fh);
$pps->NextPps = self::_readInt4($fh);
$pps->DirPps = self::_readInt4($fh);
fseek($fh, 20, SEEK_CUR);
$pps->Time1st = self::OLE2LocalDate(fread($fh, 8));
$pps->Time2nd = self::OLE2LocalDate(fread($fh, 8));
$pps->_StartBlock = self::_readInt4($fh);
$pps->Size = self::_readInt4($fh);
$pps->No = count($this->_list);
$this->_list[] = $pps;
// check if the PPS tree (starting from root) is complete
if (isset($this->root) && $this->_ppsTreeComplete($this->root->No)) {
break;
}
}
fclose($fh);
// Initialize $pps->children on directories
foreach ($this->_list as $pps) {
if ($pps->Type == self::OLE_PPS_TYPE_DIR || $pps->Type == self::OLE_PPS_TYPE_ROOT) {
$nos = array($pps->DirPps);
$pps->children = array();
while ($nos) {
$no = array_pop($nos);
if ($no != -1) {
$childPps = $this->_list[$no];
$nos[] = $childPps->PrevPps;
$nos[] = $childPps->NextPps;
$pps->children[] = $childPps;
}
}
}
}
return true;
}
/**
* It checks whether the PPS tree is complete (all PPS's read)
* starting with the given PPS (not necessarily root)
*
* @access public
* @param integer $index The index of the PPS from which we are checking
* @return boolean Whether the PPS tree for the given PPS is complete
*/
public function _ppsTreeComplete($index)
{
return isset($this->_list[$index]) &&
($pps = $this->_list[$index]) &&
($pps->PrevPps == -1 ||
$this->_ppsTreeComplete($pps->PrevPps)) &&
($pps->NextPps == -1 ||
$this->_ppsTreeComplete($pps->NextPps)) &&
($pps->DirPps == -1 ||
$this->_ppsTreeComplete($pps->DirPps));
}
/**
* Checks whether a PPS is a File PPS or not.
* If there is no PPS for the index given, it will return false.
*
* @access public
* @param integer $index The index for the PPS
* @return bool true if it's a File PPS, false otherwise
*/
public function isFile($index)
{
if (isset($this->_list[$index])) {
return ($this->_list[$index]->Type == self::OLE_PPS_TYPE_FILE);
}
return false;
}
/**
* Checks whether a PPS is a Root PPS or not.
* If there is no PPS for the index given, it will return false.
*
* @access public
* @param integer $index The index for the PPS.
* @return bool true if it's a Root PPS, false otherwise
*/
public function isRoot($index)
{
if (isset($this->_list[$index])) {
return ($this->_list[$index]->Type == self::OLE_PPS_TYPE_ROOT);
}
return false;
}
/**
* Gives the total number of PPS's found in the OLE container.
*
* @access public
* @return integer The total number of PPS's found in the OLE container
*/
public function ppsTotal()
{
return count($this->_list);
}
/**
* Gets data from a PPS
* If there is no PPS for the index given, it will return an empty string.
*
* @access public
* @param integer $index The index for the PPS
* @param integer $position The position from which to start reading
* (relative to the PPS)
* @param integer $length The amount of bytes to read (at most)
* @return string The binary string containing the data requested
* @see OLE_PPS_File::getStream()
*/
public function getData($index, $position, $length)
{
// if position is not valid return empty string
if (!isset($this->_list[$index]) || ($position >= $this->_list[$index]->Size) || ($position < 0)) {
return '';
}
$fh = $this->getStream($this->_list[$index]);
$data = stream_get_contents($fh, $length, $position);
fclose($fh);
return $data;
}
/**
* Gets the data length from a PPS
* If there is no PPS for the index given, it will return 0.
*
* @access public
* @param integer $index The index for the PPS
* @return integer The amount of bytes in data the PPS has
*/
public function getDataLength($index)
{
if (isset($this->_list[$index])) {
return $this->_list[$index]->Size;
}
return 0;
}
/**
* Utility function to transform ASCII text to Unicode
*
* @access public
* @static
* @param string $ascii The ASCII string to transform
* @return string The string in Unicode
*/
public static function Asc2Ucs($ascii)
{
$rawname = '';
for ($i = 0; $i < strlen($ascii); ++$i) {
$rawname .= $ascii{$i} . "\x00";
}
return $rawname;
}
/**
* Utility function
* Returns a string for the OLE container with the date given
*
* @access public
* @static
* @param integer $date A timestamp
* @return string The string for the OLE container
*/
public static function LocalDate2OLE($date = null)
{
if (!isset($date)) {
return "\x00\x00\x00\x00\x00\x00\x00\x00";
}
// factor used for separating numbers into 4 bytes parts
$factor = pow(2, 32);
// days from 1-1-1601 until the beggining of UNIX era
$days = 134774;
// calculate seconds
$big_date = $days*24*3600 + gmmktime(date("H", $date), date("i", $date), date("s", $date), date("m", $date), date("d", $date), date("Y", $date));
// multiply just to make MS happy
$big_date *= 10000000;
$high_part = floor($big_date / $factor);
// lower 4 bytes
$low_part = floor((($big_date / $factor) - $high_part) * $factor);
// Make HEX string
$res = '';
for ($i = 0; $i < 4; ++$i) {
$hex = $low_part % 0x100;
$res .= pack('c', $hex);
$low_part /= 0x100;
}
for ($i = 0; $i < 4; ++$i) {
$hex = $high_part % 0x100;
$res .= pack('c', $hex);
$high_part /= 0x100;
}
return $res;
}
/**
* Returns a timestamp from an OLE container's date
*
* @access public
* @static
* @param integer $string A binary string with the encoded date
* @return string The timestamp corresponding to the string
*/
public static function OLE2LocalDate($string)
{
if (strlen($string) != 8) {
return new PEAR_Error("Expecting 8 byte string");
}
// factor used for separating numbers into 4 bytes parts
$factor = pow(2, 32);
list(, $high_part) = unpack('V', substr($string, 4, 4));
list(, $low_part) = unpack('V', substr($string, 0, 4));
$big_date = ($high_part * $factor) + $low_part;
// translate to seconds
$big_date /= 10000000;
// days from 1-1-1601 until the beggining of UNIX era
$days = 134774;
// translate to seconds from beggining of UNIX era
$big_date -= $days * 24 * 3600;
return floor($big_date);
}
}

206
extend/PHPExcel/PHPExcel/Shared/OLE/ChainedBlockStream.php

@ -0,0 +1,206 @@
<?php
/**
* PHPExcel_Shared_OLE_ChainedBlockStream
*
* Copyright (c) 2006 - 2015 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_Shared_OLE
* @copyright Copyright (c) 2006 - 2007 Christian Schmidt
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_OLE_ChainedBlockStream
{
/**
* The OLE container of the file that is being read.
* @var OLE
*/
public $ole;
/**
* Parameters specified by fopen().
* @var array
*/
public $params;
/**
* The binary data of the file.
* @var string
*/
public $data;
/**
* The file pointer.
* @var int byte offset
*/
public $pos;
/**
* Implements support for fopen().
* For creating streams using this wrapper, use OLE_PPS_File::getStream().
*
* @param string $path resource name including scheme, e.g.
* ole-chainedblockstream://oleInstanceId=1
* @param string $mode only "r" is supported
* @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH
* @param string &$openedPath absolute path of the opened stream (out parameter)
* @return bool true on success
*/
public function stream_open($path, $mode, $options, &$openedPath)
{
if ($mode != 'r') {
if ($options & STREAM_REPORT_ERRORS) {
trigger_error('Only reading is supported', E_USER_WARNING);
}
return false;
}
// 25 is length of "ole-chainedblockstream://"
parse_str(substr($path, 25), $this->params);
if (!isset($this->params['oleInstanceId'], $this->params['blockId'], $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']])) {
if ($options & STREAM_REPORT_ERRORS) {
trigger_error('OLE stream not found', E_USER_WARNING);
}
return false;
}
$this->ole = $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']];
$blockId = $this->params['blockId'];
$this->data = '';
if (isset($this->params['size']) && $this->params['size'] < $this->ole->bigBlockThreshold && $blockId != $this->ole->root->_StartBlock) {
// Block id refers to small blocks
$rootPos = $this->ole->_getBlockOffset($this->ole->root->_StartBlock);
while ($blockId != -2) {
$pos = $rootPos + $blockId * $this->ole->bigBlockSize;
$blockId = $this->ole->sbat[$blockId];
fseek($this->ole->_file_handle, $pos);
$this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize);
}
} else {
// Block id refers to big blocks
while ($blockId != -2) {
$pos = $this->ole->_getBlockOffset($blockId);
fseek($this->ole->_file_handle, $pos);
$this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize);
$blockId = $this->ole->bbat[$blockId];
}
}
if (isset($this->params['size'])) {
$this->data = substr($this->data, 0, $this->params['size']);
}
if ($options & STREAM_USE_PATH) {
$openedPath = $path;
}
return true;
}
/**
* Implements support for fclose().
*
*/
public function stream_close()
{
$this->ole = null;
unset($GLOBALS['_OLE_INSTANCES']);
}
/**
* Implements support for fread(), fgets() etc.
*
* @param int $count maximum number of bytes to read
* @return string
*/
public function stream_read($count)
{
if ($this->stream_eof()) {
return false;
}
$s = substr($this->data, $this->pos, $count);
$this->pos += $count;
return $s;
}
/**
* Implements support for feof().
*
* @return bool TRUE if the file pointer is at EOF; otherwise FALSE
*/
public function stream_eof()
{
return $this->pos >= strlen($this->data);
}
/**
* Returns the position of the file pointer, i.e. its offset into the file
* stream. Implements support for ftell().
*
* @return int
*/
public function stream_tell()
{
return $this->pos;
}
/**
* Implements support for fseek().
*
* @param int $offset byte offset
* @param int $whence SEEK_SET, SEEK_CUR or SEEK_END
* @return bool
*/
public function stream_seek($offset, $whence)
{
if ($whence == SEEK_SET && $offset >= 0) {
$this->pos = $offset;
} elseif ($whence == SEEK_CUR && -$offset <= $this->pos) {
$this->pos += $offset;
} elseif ($whence == SEEK_END && -$offset <= sizeof($this->data)) {
$this->pos = strlen($this->data) + $offset;
} else {
return false;
}
return true;
}
/**
* Implements support for fstat(). Currently the only supported field is
* "size".
* @return array
*/
public function stream_stat()
{
return array(
'size' => strlen($this->data),
);
}
// Methods used by stream_wrapper_register() that are not implemented:
// bool stream_flush ( void )
// int stream_write ( string data )
// bool rename ( string path_from, string path_to )
// bool mkdir ( string path, int mode, int options )
// bool rmdir ( string path, int options )
// bool dir_opendir ( string path, int options )
// array url_stat ( string path, int flags )
// string dir_readdir ( void )
// bool dir_rewinddir ( void )
// bool dir_closedir ( void )
}

230
extend/PHPExcel/PHPExcel/Shared/OLE/PPS.php

@ -0,0 +1,230 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id: PPS.php,v 1.7 2007/02/13 21:00:42 schmidt Exp $
/**
* Class for creating PPS's for OLE containers
*
* @author Xavier Noguer <xnoguer@php.net>
* @category PHPExcel
* @package PHPExcel_Shared_OLE
*/
class PHPExcel_Shared_OLE_PPS
{
/**
* The PPS index
* @var integer
*/
public $No;
/**
* The PPS name (in Unicode)
* @var string
*/
public $Name;
/**
* The PPS type. Dir, Root or File
* @var integer
*/
public $Type;
/**
* The index of the previous PPS
* @var integer
*/
public $PrevPps;
/**
* The index of the next PPS
* @var integer
*/
public $NextPps;
/**
* The index of it's first child if this is a Dir or Root PPS
* @var integer
*/
public $DirPps;
/**
* A timestamp
* @var integer
*/
public $Time1st;
/**
* A timestamp
* @var integer
*/
public $Time2nd;
/**
* Starting block (small or big) for this PPS's data inside the container
* @var integer
*/
public $_StartBlock;
/**
* The size of the PPS's data (in bytes)
* @var integer
*/
public $Size;
/**
* The PPS's data (only used if it's not using a temporary file)
* @var string
*/
public $_data;
/**
* Array of child PPS's (only used by Root and Dir PPS's)
* @var array
*/
public $children = array();
/**
* Pointer to OLE container
* @var OLE
*/
public $ole;
/**
* The constructor
*
* @access public
* @param integer $No The PPS index
* @param string $name The PPS name
* @param integer $type The PPS type. Dir, Root or File
* @param integer $prev The index of the previous PPS
* @param integer $next The index of the next PPS
* @param integer $dir The index of it's first child if this is a Dir or Root PPS
* @param integer $time_1st A timestamp
* @param integer $time_2nd A timestamp
* @param string $data The (usually binary) source data of the PPS
* @param array $children Array containing children PPS for this PPS
*/
public function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $time_2nd, $data, $children)
{
$this->No = $No;
$this->Name = $name;
$this->Type = $type;
$this->PrevPps = $prev;
$this->NextPps = $next;
$this->DirPps = $dir;
$this->Time1st = $time_1st;
$this->Time2nd = $time_2nd;
$this->_data = $data;
$this->children = $children;
if ($data != '') {
$this->Size = strlen($data);
} else {
$this->Size = 0;
}
}
/**
* Returns the amount of data saved for this PPS
*
* @access public
* @return integer The amount of data (in bytes)
*/
public function _DataLen()
{
if (!isset($this->_data)) {
return 0;
}
//if (isset($this->_PPS_FILE)) {
// fseek($this->_PPS_FILE, 0);
// $stats = fstat($this->_PPS_FILE);
// return $stats[7];
//} else {
return strlen($this->_data);
//}
}
/**
* Returns a string with the PPS's WK (What is a WK?)
*
* @access public
* @return string The binary string
*/
public function _getPpsWk()
{
$ret = str_pad($this->Name, 64, "\x00");
$ret .= pack("v", strlen($this->Name) + 2) // 66
. pack("c", $this->Type) // 67
. pack("c", 0x00) //UK // 68
. pack("V", $this->PrevPps) //Prev // 72
. pack("V", $this->NextPps) //Next // 76
. pack("V", $this->DirPps) //Dir // 80
. "\x00\x09\x02\x00" // 84
. "\x00\x00\x00\x00" // 88
. "\xc0\x00\x00\x00" // 92
. "\x00\x00\x00\x46" // 96 // Seems to be ok only for Root
. "\x00\x00\x00\x00" // 100
. PHPExcel_Shared_OLE::LocalDate2OLE($this->Time1st) // 108
. PHPExcel_Shared_OLE::LocalDate2OLE($this->Time2nd) // 116
. pack("V", isset($this->_StartBlock)?
$this->_StartBlock:0) // 120
. pack("V", $this->Size) // 124
. pack("V", 0); // 128
return $ret;
}
/**
* Updates index and pointers to previous, next and children PPS's for this
* PPS. I don't think it'll work with Dir PPS's.
*
* @access public
* @param array &$raList Reference to the array of PPS's for the whole OLE
* container
* @return integer The index for this PPS
*/
public static function _savePpsSetPnt(&$raList, $to_save, $depth = 0)
{
if (!is_array($to_save) || (empty($to_save))) {
return 0xFFFFFFFF;
} elseif (count($to_save) == 1) {
$cnt = count($raList);
// If the first entry, it's the root... Don't clone it!
$raList[$cnt] = ( $depth == 0 ) ? $to_save[0] : clone $to_save[0];
$raList[$cnt]->No = $cnt;
$raList[$cnt]->PrevPps = 0xFFFFFFFF;
$raList[$cnt]->NextPps = 0xFFFFFFFF;
$raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++);
} else {
$iPos = floor(count($to_save) / 2);
$aPrev = array_slice($to_save, 0, $iPos);
$aNext = array_slice($to_save, $iPos + 1);
$cnt = count($raList);
// If the first entry, it's the root... Don't clone it!
$raList[$cnt] = ( $depth == 0 ) ? $to_save[$iPos] : clone $to_save[$iPos];
$raList[$cnt]->No = $cnt;
$raList[$cnt]->PrevPps = self::_savePpsSetPnt($raList, $aPrev, $depth++);
$raList[$cnt]->NextPps = self::_savePpsSetPnt($raList, $aNext, $depth++);
$raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++);
}
return $cnt;
}
}

74
extend/PHPExcel/PHPExcel/Shared/OLE/PPS/File.php

@ -0,0 +1,74 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id: File.php,v 1.11 2007/02/13 21:00:42 schmidt Exp $
/**
* Class for creating File PPS's for OLE containers
*
* @author Xavier Noguer <xnoguer@php.net>
* @category PHPExcel
* @package PHPExcel_Shared_OLE
*/
class PHPExcel_Shared_OLE_PPS_File extends PHPExcel_Shared_OLE_PPS
{
/**
* The constructor
*
* @access public
* @param string $name The name of the file (in Unicode)
* @see OLE::Asc2Ucs()
*/
public function __construct($name)
{
parent::__construct(null, $name, PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE, null, null, null, null, null, '', array());
}
/**
* Initialization method. Has to be called right after OLE_PPS_File().
*
* @access public
* @return mixed true on success
*/
public function init()
{
return true;
}
/**
* Append data to PPS
*
* @access public
* @param string $data The data to append
*/
public function append($data)
{
$this->_data .= $data;
}
/**
* Returns a stream for reading this file using fread() etc.
* @return resource a read-only stream
*/
public function getStream()
{
$this->ole->getStream($this);
}
}

462
extend/PHPExcel/PHPExcel/Shared/OLE/PPS/Root.php

@ -0,0 +1,462 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Xavier Noguer <xnoguer@php.net> |
// | Based on OLE::Storage_Lite by Kawai, Takanori |
// +----------------------------------------------------------------------+
//
// $Id: Root.php,v 1.9 2005/04/23 21:53:49 dufuz Exp $
/**
* Class for creating Root PPS's for OLE containers
*
* @author Xavier Noguer <xnoguer@php.net>
* @category PHPExcel
* @package PHPExcel_Shared_OLE
*/
class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS
{
/**
* Directory for temporary files
* @var string
*/
protected $tempDirectory = null;
/**
* @param integer $time_1st A timestamp
* @param integer $time_2nd A timestamp
*/
public function __construct($time_1st, $time_2nd, $raChild)
{
$this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir();
parent::__construct(null, PHPExcel_Shared_OLE::Asc2Ucs('Root Entry'), PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT, null, null, null, $time_1st, $time_2nd, null, $raChild);
}
/**
* Method for saving the whole OLE container (including files).
* In fact, if called with an empty argument (or '-'), it saves to a
* temporary file and then outputs it's contents to stdout.
* If a resource pointer to a stream created by fopen() is passed
* it will be used, but you have to close such stream by yourself.
*
* @param string|resource $filename The name of the file or stream where to save the OLE container.
* @access public
* @return mixed true on success
*/
public function save($filename)
{
// Initial Setting for saving
$this->_BIG_BLOCK_SIZE = pow(
2,
(isset($this->_BIG_BLOCK_SIZE))? self::adjust2($this->_BIG_BLOCK_SIZE) : 9
);
$this->_SMALL_BLOCK_SIZE= pow(
2,
(isset($this->_SMALL_BLOCK_SIZE))? self::adjust2($this->_SMALL_BLOCK_SIZE) : 6
);
if (is_resource($filename)) {
$this->_FILEH_ = $filename;
} elseif ($filename == '-' || $filename == '') {
if ($this->tempDirectory === null) {
$this->tempDirectory = PHPExcel_Shared_File::sys_get_temp_dir();
}
$this->_tmp_filename = tempnam($this->tempDirectory, "OLE_PPS_Root");
$this->_FILEH_ = fopen($this->_tmp_filename, "w+b");
if ($this->_FILEH_ == false) {
throw new PHPExcel_Writer_Exception("Can't create temporary file.");
}
} else {
$this->_FILEH_ = fopen($filename, "wb");
}
if ($this->_FILEH_ == false) {
throw new PHPExcel_Writer_Exception("Can't open $filename. It may be in use or protected.");
}
// Make an array of PPS's (for Save)
$aList = array();
PHPExcel_Shared_OLE_PPS::_savePpsSetPnt($aList, array($this));
// calculate values for header
list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo);
// Save Header
$this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
// Make Small Data string (write SBD)
$this->_data = $this->_makeSmallData($aList);
// Write BB
$this->_saveBigData($iSBDcnt, $aList);
// Write PPS
$this->_savePps($aList);
// Write Big Block Depot and BDList and Adding Header informations
$this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
if (!is_resource($filename)) {
fclose($this->_FILEH_);
}
return true;
}
/**
* Calculate some numbers
*
* @access public
* @param array $raList Reference to an array of PPS's
* @return array The array of numbers
*/
public function _calcSize(&$raList)
{
// Calculate Basic Setting
list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0);
$iSmallLen = 0;
$iSBcnt = 0;
$iCount = count($raList);
for ($i = 0; $i < $iCount; ++$i) {
if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) {
$raList[$i]->Size = $raList[$i]->_DataLen();
if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) {
$iSBcnt += floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
+ (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
} else {
$iBBcnt += (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
(($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
}
}
}
$iSmallLen = $iSBcnt * $this->_SMALL_BLOCK_SIZE;
$iSlCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE);
$iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt)? 1:0);
$iBBcnt += (floor($iSmallLen / $this->_BIG_BLOCK_SIZE) +
(( $iSmallLen % $this->_BIG_BLOCK_SIZE)? 1: 0));
$iCnt = count($raList);
$iBdCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE;
$iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0));
return array($iSBDcnt, $iBBcnt, $iPPScnt);
}
/**
* Helper function for caculating a magic value for block sizes
*
* @access public
* @param integer $i2 The argument
* @see save()
* @return integer
*/
private static function adjust2($i2)
{
$iWk = log($i2)/log(2);
return ($iWk > floor($iWk))? floor($iWk)+1:$iWk;
}
/**
* Save OLE header
*
* @access public
* @param integer $iSBDcnt
* @param integer $iBBcnt
* @param integer $iPPScnt
*/
public function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt)
{
$FILE = $this->_FILEH_;
// Calculate Basic Setting
$iBlCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE;
$i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE;
$iBdExL = 0;
$iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
$iAllW = $iAll;
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
$iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
// Calculate BD count
if ($iBdCnt > $i1stBdL) {
while (1) {
++$iBdExL;
++$iAllW;
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0);
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0);
if ($iBdCnt <= ($iBdExL*$iBlCnt+ $i1stBdL)) {
break;
}
}
}
// Save Header
fwrite(
$FILE,
"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"
. "\x00\x00\x00\x00"
. "\x00\x00\x00\x00"
. "\x00\x00\x00\x00"
. "\x00\x00\x00\x00"
. pack("v", 0x3b)
. pack("v", 0x03)
. pack("v", -2)
. pack("v", 9)
. pack("v", 6)
. pack("v", 0)
. "\x00\x00\x00\x00"
. "\x00\x00\x00\x00"
. pack("V", $iBdCnt)
. pack("V", $iBBcnt+$iSBDcnt) //ROOT START
. pack("V", 0)
. pack("V", 0x1000)
. pack("V", $iSBDcnt ? 0 : -2) //Small Block Depot
. pack("V", $iSBDcnt)
);
// Extra BDList Start, Count
if ($iBdCnt < $i1stBdL) {
fwrite(
$FILE,
pack("V", -2) // Extra BDList Start
. pack("V", 0)// Extra BDList Count
);
} else {
fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL));
}
// BDList
for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) {
fwrite($FILE, pack("V", $iAll+$i));
}
if ($i < $i1stBdL) {
$jB = $i1stBdL - $i;
for ($j = 0; $j < $jB; ++$j) {
fwrite($FILE, (pack("V", -1)));
}
}
}
/**
* Saving big data (PPS's with data bigger than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL)
*
* @access public
* @param integer $iStBlk
* @param array &$raList Reference to array of PPS's
*/
public function _saveBigData($iStBlk, &$raList)
{
$FILE = $this->_FILEH_;
// cycle through PPS's
$iCount = count($raList);
for ($i = 0; $i < $iCount; ++$i) {
if ($raList[$i]->Type != PHPExcel_Shared_OLE::OLE_PPS_TYPE_DIR) {
$raList[$i]->Size = $raList[$i]->_DataLen();
if (($raList[$i]->Size >= PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) || (($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) {
// Write Data
//if (isset($raList[$i]->_PPS_FILE)) {
// $iLen = 0;
// fseek($raList[$i]->_PPS_FILE, 0); // To The Top
// while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) {
// $iLen += strlen($sBuff);
// fwrite($FILE, $sBuff);
// }
//} else {
fwrite($FILE, $raList[$i]->_data);
//}
if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) {
fwrite($FILE, str_repeat("\x00", $this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)));
}
// Set For PPS
$raList[$i]->_StartBlock = $iStBlk;
$iStBlk +=
(floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) +
(($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0));
}
// Close file for each PPS, and unlink it
//if (isset($raList[$i]->_PPS_FILE)) {
// fclose($raList[$i]->_PPS_FILE);
// $raList[$i]->_PPS_FILE = null;
// unlink($raList[$i]->_tmp_filename);
//}
}
}
}
/**
* get small data (PPS's with data smaller than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL)
*
* @access public
* @param array &$raList Reference to array of PPS's
*/
public function _makeSmallData(&$raList)
{
$sRes = '';
$FILE = $this->_FILEH_;
$iSmBlk = 0;
$iCount = count($raList);
for ($i = 0; $i < $iCount; ++$i) {
// Make SBD, small data string
if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) {
if ($raList[$i]->Size <= 0) {
continue;
}
if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) {
$iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE)
+ (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0);
// Add to SBD
$jB = $iSmbCnt - 1;
for ($j = 0; $j < $jB; ++$j) {
fwrite($FILE, pack("V", $j+$iSmBlk+1));
}
fwrite($FILE, pack("V", -2));
//// Add to Data String(this will be written for RootEntry)
//if ($raList[$i]->_PPS_FILE) {
// fseek($raList[$i]->_PPS_FILE, 0); // To The Top
// while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) {
// $sRes .= $sBuff;
// }
//} else {
$sRes .= $raList[$i]->_data;
//}
if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) {
$sRes .= str_repeat("\x00", $this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE));
}
// Set for PPS
$raList[$i]->_StartBlock = $iSmBlk;
$iSmBlk += $iSmbCnt;
}
}
}
$iSbCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE);
if ($iSmBlk % $iSbCnt) {
$iB = $iSbCnt - ($iSmBlk % $iSbCnt);
for ($i = 0; $i < $iB; ++$i) {
fwrite($FILE, pack("V", -1));
}
}
return $sRes;
}
/**
* Saves all the PPS's WKs
*
* @access public
* @param array $raList Reference to an array with all PPS's
*/
public function _savePps(&$raList)
{
// Save each PPS WK
$iC = count($raList);
for ($i = 0; $i < $iC; ++$i) {
fwrite($this->_FILEH_, $raList[$i]->_getPpsWk());
}
// Adjust for Block
$iCnt = count($raList);
$iBCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE;
if ($iCnt % $iBCnt) {
fwrite($this->_FILEH_, str_repeat("\x00", ($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE));
}
}
/**
* Saving Big Block Depot
*
* @access public
* @param integer $iSbdSize
* @param integer $iBsize
* @param integer $iPpsCnt
*/
public function _saveBbd($iSbdSize, $iBsize, $iPpsCnt)
{
$FILE = $this->_FILEH_;
// Calculate Basic Setting
$iBbCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE;
$i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE;
$iBdExL = 0;
$iAll = $iBsize + $iPpsCnt + $iSbdSize;
$iAllW = $iAll;
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
$iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
// Calculate BD count
if ($iBdCnt >$i1stBdL) {
while (1) {
++$iBdExL;
++$iAllW;
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0);
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
if ($iBdCnt <= ($iBdExL*$iBbCnt+ $i1stBdL)) {
break;
}
}
}
// Making BD
// Set for SBD
if ($iSbdSize > 0) {
for ($i = 0; $i < ($iSbdSize - 1); ++$i) {
fwrite($FILE, pack("V", $i+1));
}
fwrite($FILE, pack("V", -2));
}
// Set for B
for ($i = 0; $i < ($iBsize - 1); ++$i) {
fwrite($FILE, pack("V", $i+$iSbdSize+1));
}
fwrite($FILE, pack("V", -2));
// Set for PPS
for ($i = 0; $i < ($iPpsCnt - 1); ++$i) {
fwrite($FILE, pack("V", $i+$iSbdSize+$iBsize+1));
}
fwrite($FILE, pack("V", -2));
// Set for BBD itself ( 0xFFFFFFFD : BBD)
for ($i = 0; $i < $iBdCnt; ++$i) {
fwrite($FILE, pack("V", 0xFFFFFFFD));
}
// Set for ExtraBDList
for ($i = 0; $i < $iBdExL; ++$i) {
fwrite($FILE, pack("V", 0xFFFFFFFC));
}
// Adjust for Block
if (($iAllW + $iBdCnt) % $iBbCnt) {
$iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt));
for ($i = 0; $i < $iBlock; ++$i) {
fwrite($FILE, pack("V", -1));
}
}
// Extra BDList
if ($iBdCnt > $i1stBdL) {
$iN=0;
$iNb=0;
for ($i = $i1stBdL; $i < $iBdCnt; $i++, ++$iN) {
if ($iN >= ($iBbCnt - 1)) {
$iN = 0;
++$iNb;
fwrite($FILE, pack("V", $iAll+$iBdCnt+$iNb));
}
fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i));
}
if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) {
$iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1));
for ($i = 0; $i < $iB; ++$i) {
fwrite($FILE, pack("V", -1));
}
}
fwrite($FILE, pack("V", -2));
}
}
}

318
extend/PHPExcel/PHPExcel/Shared/OLERead.php

@ -0,0 +1,318 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
defined('IDENTIFIER_OLE') ||
define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1));
class PHPExcel_Shared_OLERead
{
private $data = '';
// OLE identifier
const IDENTIFIER_OLE = IDENTIFIER_OLE;
// Size of a sector = 512 bytes
const BIG_BLOCK_SIZE = 0x200;
// Size of a short sector = 64 bytes
const SMALL_BLOCK_SIZE = 0x40;
// Size of a directory entry always = 128 bytes
const PROPERTY_STORAGE_BLOCK_SIZE = 0x80;
// Minimum size of a standard stream = 4096 bytes, streams smaller than this are stored as short streams
const SMALL_BLOCK_THRESHOLD = 0x1000;
// header offsets
const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c;
const ROOT_START_BLOCK_POS = 0x30;
const SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c;
const EXTENSION_BLOCK_POS = 0x44;
const NUM_EXTENSION_BLOCK_POS = 0x48;
const BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c;
// property storage offsets (directory offsets)
const SIZE_OF_NAME_POS = 0x40;
const TYPE_POS = 0x42;
const START_BLOCK_POS = 0x74;
const SIZE_POS = 0x78;
public $wrkbook = null;
public $summaryInformation = null;
public $documentSummaryInformation = null;
/**
* Read the file
*
* @param $sFileName string Filename
* @throws PHPExcel_Reader_Exception
*/
public function read($sFileName)
{
// Check if file exists and is readable
if (!is_readable($sFileName)) {
throw new PHPExcel_Reader_Exception("Could not open " . $sFileName . " for reading! File does not exist, or it is not readable.");
}
// Get the file identifier
// Don't bother reading the whole file until we know it's a valid OLE file
$this->data = file_get_contents($sFileName, false, null, 0, 8);
// Check OLE identifier
if ($this->data != self::IDENTIFIER_OLE) {
throw new PHPExcel_Reader_Exception('The filename ' . $sFileName . ' is not recognised as an OLE file');
}
// Get the file data
$this->data = file_get_contents($sFileName);
// Total number of sectors used for the SAT
$this->numBigBlockDepotBlocks = self::getInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
// SecID of the first sector of the directory stream
$this->rootStartBlock = self::getInt4d($this->data, self::ROOT_START_BLOCK_POS);
// SecID of the first sector of the SSAT (or -2 if not extant)
$this->sbdStartBlock = self::getInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS);
// SecID of the first sector of the MSAT (or -2 if no additional sectors are used)
$this->extensionBlock = self::getInt4d($this->data, self::EXTENSION_BLOCK_POS);
// Total number of sectors used by MSAT
$this->numExtensionBlocks = self::getInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS);
$bigBlockDepotBlocks = array();
$pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS;
$bbdBlocks = $this->numBigBlockDepotBlocks;
if ($this->numExtensionBlocks != 0) {
$bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
}
for ($i = 0; $i < $bbdBlocks; ++$i) {
$bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos);
$pos += 4;
}
for ($j = 0; $j < $this->numExtensionBlocks; ++$j) {
$pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE;
$blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1);
for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) {
$bigBlockDepotBlocks[$i] = self::getInt4d($this->data, $pos);
$pos += 4;
}
$bbdBlocks += $blocksToRead;
if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
$this->extensionBlock = self::getInt4d($this->data, $pos);
}
}
$pos = 0;
$this->bigBlockChain = '';
$bbs = self::BIG_BLOCK_SIZE / 4;
for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
$this->bigBlockChain .= substr($this->data, $pos, 4*$bbs);
$pos += 4*$bbs;
}
$pos = 0;
$sbdBlock = $this->sbdStartBlock;
$this->smallBlockChain = '';
while ($sbdBlock != -2) {
$pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
$this->smallBlockChain .= substr($this->data, $pos, 4*$bbs);
$pos += 4*$bbs;
$sbdBlock = self::getInt4d($this->bigBlockChain, $sbdBlock*4);
}
// read the directory stream
$block = $this->rootStartBlock;
$this->entry = $this->_readData($block);
$this->readPropertySets();
}
/**
* Extract binary stream data
*
* @return string
*/
public function getStream($stream)
{
if ($stream === null) {
return null;
}
$streamData = '';
if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) {
$rootdata = $this->_readData($this->props[$this->rootentry]['startBlock']);
$block = $this->props[$stream]['startBlock'];
while ($block != -2) {
$pos = $block * self::SMALL_BLOCK_SIZE;
$streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE);
$block = self::getInt4d($this->smallBlockChain, $block*4);
}
return $streamData;
} else {
$numBlocks = $this->props[$stream]['size'] / self::BIG_BLOCK_SIZE;
if ($this->props[$stream]['size'] % self::BIG_BLOCK_SIZE != 0) {
++$numBlocks;
}
if ($numBlocks == 0) {
return '';
}
$block = $this->props[$stream]['startBlock'];
while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = self::getInt4d($this->bigBlockChain, $block*4);
}
return $streamData;
}
}
/**
* Read a standard stream (by joining sectors using information from SAT)
*
* @param int $bl Sector ID where the stream starts
* @return string Data for standard stream
*/
private function _readData($bl)
{
$block = $bl;
$data = '';
while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = self::getInt4d($this->bigBlockChain, $block*4);
}
return $data;
}
/**
* Read entries in the directory stream.
*/
private function readPropertySets()
{
$offset = 0;
// loop through entires, each entry is 128 bytes
$entryLen = strlen($this->entry);
while ($offset < $entryLen) {
// entry data (128 bytes)
$d = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE);
// size in bytes of name
$nameSize = ord($d[self::SIZE_OF_NAME_POS]) | (ord($d[self::SIZE_OF_NAME_POS+1]) << 8);
// type of entry
$type = ord($d[self::TYPE_POS]);
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook)
// sectorID of first sector of the short-stream container stream, if this entry is root entry
$startBlock = self::getInt4d($d, self::START_BLOCK_POS);
$size = self::getInt4d($d, self::SIZE_POS);
$name = str_replace("\x00", "", substr($d, 0, $nameSize));
$this->props[] = array(
'name' => $name,
'type' => $type,
'startBlock' => $startBlock,
'size' => $size
);
// tmp helper to simplify checks
$upName = strtoupper($name);
// Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook)
if (($upName === 'WORKBOOK') || ($upName === 'BOOK')) {
$this->wrkbook = count($this->props) - 1;
} elseif ($upName === 'ROOT ENTRY' || $upName === 'R') {
// Root entry
$this->rootentry = count($this->props) - 1;
}
// Summary information
if ($name == chr(5) . 'SummaryInformation') {
// echo 'Summary Information<br />';
$this->summaryInformation = count($this->props) - 1;
}
// Additional Document Summary information
if ($name == chr(5) . 'DocumentSummaryInformation') {
// echo 'Document Summary Information<br />';
$this->documentSummaryInformation = count($this->props) - 1;
}
$offset += self::PROPERTY_STORAGE_BLOCK_SIZE;
}
}
/**
* Read 4 bytes of data at specified position
*
* @param string $data
* @param int $pos
* @return int
*/
private static function getInt4d($data, $pos)
{
// FIX: represent numbers correctly on 64-bit system
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
$_or_24 = ord($data[$pos + 3]);
if ($_or_24 >= 128) {
// negative number
$_ord_24 = -abs((256 - $_or_24) << 24);
} else {
$_ord_24 = ($_or_24 & 127) << 24;
}
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24;
}
}

504
extend/PHPExcel/PHPExcel/Shared/PCLZip/gnu-lgpl.txt

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

5173
extend/PHPExcel/PHPExcel/Shared/PCLZip/pclzip.lib.php

File diff suppressed because it is too large

421
extend/PHPExcel/PHPExcel/Shared/PCLZip/readme.txt

@ -0,0 +1,421 @@
// --------------------------------------------------------------------------------
// PclZip 2.8.2 - readme.txt
// --------------------------------------------------------------------------------
// License GNU/LGPL - August 2009
// Vincent Blavet - vincent@phpconcept.net
// http://www.phpconcept.net
// --------------------------------------------------------------------------------
// $Id: readme.txt,v 1.60 2009/09/30 20:35:21 vblavet Exp $
// --------------------------------------------------------------------------------
0 - Sommaire
============
1 - Introduction
2 - What's new
3 - Corrected bugs
4 - Known bugs or limitations
5 - License
6 - Warning
7 - Documentation
8 - Author
9 - Contribute
1 - Introduction
================
PclZip is a library that allow you to manage a Zip archive.
Full documentation about PclZip can be found here : http://www.phpconcept.net/pclzip
2 - What's new
==============
Version 2.8.2 :
- PCLZIP_CB_PRE_EXTRACT and PCLZIP_CB_POST_EXTRACT are now supported with
extraction as a string (PCLZIP_OPT_EXTRACT_AS_STRING). The string
can also be modified in the post-extract call back.
**Bugs correction :
- PCLZIP_OPT_REMOVE_ALL_PATH was not working correctly
- Remove use of eval() and do direct call to callback functions
- Correct support of 64bits systems (Thanks to WordPress team)
Version 2.8.1 :
- Move option PCLZIP_OPT_BY_EREG to PCLZIP_OPT_BY_PREG because ereg() is
deprecated in PHP 5.3. When using option PCLZIP_OPT_BY_EREG, PclZip will
automatically replace it by PCLZIP_OPT_BY_PREG.
Version 2.8 :
- Improve extraction of zip archive for large files by using temporary files
This feature is working like the one defined in r2.7.
Options are renamed : PCLZIP_OPT_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_OFF,
PCLZIP_OPT_TEMP_FILE_THRESHOLD
- Add a ratio constant PCLZIP_TEMPORARY_FILE_RATIO to configure the auto
sense of temporary file use.
- Bug correction : Reduce filepath in returned file list to remove ennoying
'.//' preambule in file path.
Version 2.7 :
- Improve creation of zip archive for large files :
PclZip will now autosense the configured memory and use temporary files
when large file is suspected.
This feature can also ne triggered by manual options in create() and add()
methods. 'PCLZIP_OPT_ADD_TEMP_FILE_ON' force the use of temporary files,
'PCLZIP_OPT_ADD_TEMP_FILE_OFF' disable the autosense technic,
'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD' allow for configuration of a size
threshold to use temporary files.
Using "temporary files" rather than "memory" might take more time, but
might give the ability to zip very large files :
Tested on my win laptop with a 88Mo file :
Zip "in-memory" : 18sec (max_execution_time=30, memory_limit=180Mo)
Zip "tmporary-files" : 23sec (max_execution_time=30, memory_limit=30Mo)
- Replace use of mktime() by time() to limit the E_STRICT error messages.
- Bug correction : When adding files with full windows path (drive letter)
PclZip is now working. Before, if the drive letter is not the default
path, PclZip was not able to add the file.
Version 2.6 :
- Code optimisation
- New attributes PCLZIP_ATT_FILE_COMMENT gives the ability to
add a comment for a specific file. (Don't really know if this is usefull)
- New attribute PCLZIP_ATT_FILE_CONTENT gives the ability to add a string
as a file.
- New attribute PCLZIP_ATT_FILE_MTIME modify the timestamp associated with
a file.
- Correct a bug. Files archived with a timestamp with 0h0m0s were extracted
with current time
- Add CRC value in the informations returned back for each file after an
action.
- Add missing closedir() statement.
- When adding a folder, and removing the path of this folder, files were
incorrectly added with a '/' at the beginning. Which means files are
related to root in unix systems. Corrected.
- Add conditional if before constant definition. This will allow users
to redefine constants without changing the file, and then improve
upgrade of pclzip code for new versions.
Version 2.5 :
- Introduce the ability to add file/folder with individual properties (file descriptor).
This gives for example the ability to change the filename of a zipped file.
. Able to add files individually
. Able to change full name
. Able to change short name
. Compatible with global options
- New attributes : PCLZIP_ATT_FILE_NAME, PCLZIP_ATT_FILE_NEW_SHORT_NAME, PCLZIP_ATT_FILE_NEW_FULL_NAME
- New error code : PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE
- Add a security control feature. PclZip can extract any file in any folder
of a system. People may use this to upload a zip file and try to override
a system file. The PCLZIP_OPT_EXTRACT_DIR_RESTRICTION will give the
ability to forgive any directory transversal behavior.
- New PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : check extraction path
- New error code : PCLZIP_ERR_DIRECTORY_RESTRICTION
- Modification in PclZipUtilPathInclusion() : dir and path beginning with ./ will be prepend
by current path (getcwd())
Version 2.4 :
- Code improvment : try to speed up the code by removing unusefull call to pack()
- Correct bug in delete() : delete() should be called with no argument. This was not
the case in 2.3. This is corrected in 2.4.
- Correct a bug in path_inclusion function. When the path has several '../../', the
result was bad.
- Add a check for magic_quotes_runtime configuration. If enabled, PclZip will
disable it while working and det it back to its original value.
This resolve a lots of bad formated archive errors.
- Bug correction : PclZip now correctly unzip file in some specific situation,
when compressed content has same size as uncompressed content.
- Bug correction : When selecting option 'PCLZIP_OPT_REMOVE_ALL_PATH',
directories are not any more created.
- Code improvment : correct unclosed opendir(), better handling of . and .. in
loops.
Version 2.3 :
- Correct a bug with PHP5 : affecting the value 0xFE49FFE0 to a variable does not
give the same result in PHP4 and PHP5 ....
Version 2.2 :
- Try development of PCLZIP_OPT_CRYPT .....
However this becomes to a stop. To crypt/decrypt I need to multiply 2 long integers,
the result (greater than a long) is not supported by PHP. Even the use of bcmath
functions does not help. I did not find yet a solution ...;
- Add missing '/' at end of directory entries
- Check is a file is encrypted or not. Returns status 'unsupported_encryption' and/or
error code PCLZIP_ERR_UNSUPPORTED_ENCRYPTION.
- Corrected : Bad "version need to extract" field in local file header
- Add private method privCheckFileHeaders() in order to check local and central
file headers. PclZip is now supporting purpose bit flag bit 3. Purpose bit flag bit 3 gives
the ability to have a local file header without size, compressed size and crc filled.
- Add a generic status 'error' for file status
- Add control of compression type. PclZip only support deflate compression method.
Before v2.2, PclZip does not check the compression method used in an archive while
extracting. With v2.2 PclZip returns a new error status for a file using an unsupported
compression method. New status is "unsupported_compression". New error code is
PCLZIP_ERR_UNSUPPORTED_COMPRESSION.
- Add optional attribute PCLZIP_OPT_STOP_ON_ERROR. This will stop the extract of files
when errors like 'a folder with same name exists' or 'a newer file exists' or
'a write protected file' exists, rather than set a status for the concerning file
and resume the extract of the zip.
- Add optional attribute PCLZIP_OPT_REPLACE_NEWER. This will force, during an extract' the
replacement of the file, even if a newer version of the file exists.
Note that today if a file with the same name already exists but is older it will be
replaced by the extracted one.
- Improve PclZipUtilOption()
- Support of zip archive with trailing bytes. Before 2.2, PclZip checks that the central
directory structure is the last data in the archive. Crypt encryption/decryption of
zip archive put trailing 0 bytes after decryption. PclZip is now supporting this.
Version 2.1 :
- Add the ability to abort the extraction by using a user callback function.
The user can now return the value '2' in its callback which indicates to stop the
extraction. For a pre call-back extract is stopped before the extration of the current
file. For a post call back, the extraction is stopped after.
- Add the ability to extract a file (or several files) directly in the standard output.
This is done by the new parameter PCLZIP_OPT_EXTRACT_IN_OUTPUT with method extract().
- Add support for parameters PCLZIP_OPT_COMMENT, PCLZIP_OPT_ADD_COMMENT,
PCLZIP_OPT_PREPEND_COMMENT. This will create, replace, add, or prepend comments
in the zip archive.
- When merging two archives, the comments are not any more lost, but merged, with a
blank space separator.
- Corrected bug : Files are not deleted when all files are asked to be deleted.
- Corrected bug : Folders with name '0' made PclZip to abort the create or add feature.
Version 2.0 :
***** Warning : Some new features may break the backward compatibility for your scripts.
Please carefully read the readme file.
- Add the ability to delete by Index, name and regular expression. This feature is
performed by the method delete(), which uses the optional parameters
PCLZIP_OPT_BY_INDEX, PCLZIP_OPT_BY_NAME, PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG.
- Add the ability to extract by regular expression. To extract by regexp you must use the method
extract(), with the option PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG
(depending if you want to use ereg() or preg_match() syntax) followed by the
regular expression pattern.
- Add the ability to extract by index, directly with the extract() method. This is a
code improvment of the extractByIndex() method.
- Add the ability to extract by name. To extract by name you must use the method
extract(), with the option PCLZIP_OPT_BY_NAME followed by the filename to
extract or an array of filenames to extract. To extract all a folder, use the folder
name rather than the filename with a '/' at the end.
- Add the ability to add files without compression. This is done with a new attribute
which is PCLZIP_OPT_NO_COMPRESSION.
- Add the attribute PCLZIP_OPT_EXTRACT_AS_STRING, which allow to extract a file directly
in a string without using any file (or temporary file).
- Add constant PCLZIP_SEPARATOR for static configuration of filename separators in a single string.
The default separator is now a comma (,) and not any more a blank space.
THIS BREAK THE BACKWARD COMPATIBILITY : Please check if this may have an impact with
your script.
- Improve algorythm performance by removing the use of temporary files when adding or
extracting files in an archive.
- Add (correct) detection of empty filename zipping. This can occurs when the removed
path is the same
as a zipped dir. The dir is not zipped (['status'] = filtered), only its content.
- Add better support for windows paths (thanks for help from manus@manusfreedom.com).
- Corrected bug : When the archive file already exists with size=0, the add() method
fails. Corrected in 2.0.
- Remove the use of OS_WINDOWS constant. Use php_uname() function rather.
- Control the order of index ranges in extract by index feature.
- Change the internal management of folders (better handling of internal flag).
Version 1.3 :
- Removing the double include check. This is now done by include_once() and require_once()
PHP directives.
- Changing the error handling mecanism : Remove the use of an external error library.
The former PclError...() functions are replaced by internal equivalent methods.
By changing the environment variable PCLZIP_ERROR_EXTERNAL you can still use the former library.
Introducing the use of constants for error codes rather than integer values. This will help
in futur improvment.
Introduction of error handling functions like errorCode(), errorName() and errorInfo().
- Remove the deprecated use of calling function with arguments passed by reference.
- Add the calling of extract(), extractByIndex(), create() and add() functions
with variable options rather than fixed arguments.
- Add the ability to remove all the file path while extracting or adding,
without any need to specify the path to remove.
This is available for extract(), extractByIndex(), create() and add() functionS by using
the new variable options parameters :
- PCLZIP_OPT_REMOVE_ALL_PATH : by indicating this option while calling the fct.
- Ability to change the mode of a file after the extraction (chmod()).
This is available for extract() and extractByIndex() functionS by using
the new variable options parameters.
- PCLZIP_OPT_SET_CHMOD : by setting the value of this option.
- Ability to definition call-back options. These call-back will be called during the adding,
or the extracting of file (extract(), extractByIndex(), create() and add() functions) :
- PCLZIP_CB_PRE_EXTRACT : will be called before each extraction of a file. The user
can trigerred the change the filename of the extracted file. The user can triggered the
skip of the extraction. This is adding a 'skipped' status in the file list result value.
- PCLZIP_CB_POST_EXTRACT : will be called after each extraction of a file.
Nothing can be triggered from that point.
- PCLZIP_CB_PRE_ADD : will be called before each add of a file. The user
can trigerred the change the stored filename of the added file. The user can triggered the
skip of the add. This is adding a 'skipped' status in the file list result value.
- PCLZIP_CB_POST_ADD : will be called after each add of a file.
Nothing can be triggered from that point.
- Two status are added in the file list returned as function result : skipped & filename_too_long
'skipped' is used when a call-back function ask for skipping the file.
'filename_too_long' is used while adding a file with a too long filename to archive (the file is
not added)
- Adding the function PclZipUtilPathInclusion(), that check the inclusion of a path into
a directory.
- Add a check of the presence of the archive file before some actions (like list, ...)
- Add the initialisation of field "index" in header array. This means that by
default index will be -1 when not explicitly set by the methods.
Version 1.2 :
- Adding a duplicate function.
- Adding a merge function. The merge function is a "quick merge" function,
it just append the content of an archive at the end of the first one. There
is no check for duplicate files or more recent files.
- Improve the search of the central directory end.
Version 1.1.2 :
- Changing the license of PclZip. PclZip is now released under the GNU / LGPL license
(see License section).
- Adding the optional support of a static temporary directory. You will need to configure
the constant PCLZIP_TEMPORARY_DIR if you want to use this feature.
- Improving the rename() function. In some cases rename() does not work (different
Filesystems), so it will be replaced by a copy() + unlink() functions.
Version 1.1.1 :
- Maintenance release, no new feature.
Version 1.1 :
- New method Add() : adding files in the archive
- New method ExtractByIndex() : partial extract of the archive, files are identified by
their index in the archive
- New method DeleteByIndex() : delete some files/folder entries from the archive,
files are identified by their index in the archive.
- Adding a test of the zlib extension presence. If not present abort the script.
Version 1.0.1 :
- No new feature
3 - Corrected bugs
==================
Corrected in Version 2.0 :
- Corrected : During an extraction, if a call-back fucntion is used and try to skip
a file, all the extraction process is stopped.
Corrected in Version 1.3 :
- Corrected : Support of static synopsis for method extract() is broken.
- Corrected : invalid size of archive content field (0xFF) should be (0xFFFF).
- Corrected : When an extract is done with a remove_path parameter, the entry for
the directory with exactly the same path is not skipped/filtered.
- Corrected : extractByIndex() and deleteByIndex() were not managing index in the
right way. For example indexes '1,3-5,11' will only extract files 1 and 11. This
is due to a sort of the index resulting table that puts 11 before 3-5 (sort on
string and not interger). The sort is temporarilly removed, this means that
you must provide a sorted list of index ranges.
Corrected in Version 1.2 :
- Nothing.
Corrected in Version 1.1.2 :
- Corrected : Winzip is unable to delete or add new files in a PclZip created archives.
Corrected in Version 1.1.1 :
- Corrected : When archived file is not compressed (0% compression), the
extract method fails.
Corrected in Version 1.1 :
- Corrected : Adding a complete tree of folder may result in a bad archive
creation.
Corrected in Version 1.0.1 :
- Corrected : Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024).
4 - Known bugs or limitations
=============================
Please publish bugs reports in SourceForge :
http://sourceforge.net/tracker/?group_id=40254&atid=427564
In Version 2.x :
- PclZip does only support file uncompressed or compressed with deflate (compression method 8)
- PclZip does not support password protected zip archive
- Some concern were seen when changing mtime of a file while archiving.
Seems to be linked to Daylight Saving Time (PclTest_changing_mtime).
In Version 1.2 :
- merge() methods does not check for duplicate files or last date of modifications.
In Version 1.1 :
- Limitation : Using 'extract' fields in the file header in the zip archive is not supported.
- WinZip is unable to delete a single file in a PclZip created archive. It is also unable to
add a file in a PclZip created archive. (Corrected in v.1.2)
In Version 1.0.1 :
- Adding a complete tree of folder may result in a bad archive
creation. (Corrected in V.1.1).
- Path given to methods must be in the unix format (/) and not the Windows format (\).
Workaround : Use only / directory separators.
- PclZip is using temporary files that are sometime the name of the file with a .tmp or .gz
added suffix. Files with these names may already exist and may be overwritten.
Workaround : none.
- PclZip does not check if the zlib extension is present. If it is absent, the zip
file is not created and the lib abort without warning.
Workaround : enable the zlib extension on the php install
In Version 1.0 :
- Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024).
(Corrected in v.1.0.1)
- Limitation : Multi-disk zip archive are not supported.
5 - License
===========
Since version 1.1.2, PclZip Library is released under GNU/LGPL license.
This library is free, so you can use it at no cost.
HOWEVER, if you release a script, an application, a library or any kind of
code using PclZip library (or a part of it), YOU MUST :
- Indicate in the documentation (or a readme file), that your work
uses PclZip Library, and make a reference to the author and the web site
http://www.phpconcept.net
- Gives the ability to the final user to update the PclZip libary.
I will also appreciate that you send me a mail (vincent@phpconcept.net), just to
be aware that someone is using PclZip.
For more information about GNU/LGPL license : http://www.gnu.org
6 - Warning
=================
This library and the associated files are non commercial, non professional work.
It should not have unexpected results. However if any damage is caused by this software
the author can not be responsible.
The use of this software is at the risk of the user.
7 - Documentation
=================
PclZip User Manuel is available in English on PhpConcept : http://www.phpconcept.net/pclzip/man/en/index.php
A Russian translation was done by Feskov Kuzma : http://php.russofile.ru/ru/authors/unsort/zip/
8 - Author
==========
This software was written by Vincent Blavet (vincent@phpconcept.net) on its leasure time.
9 - Contribute
==============
If you want to contribute to the development of PclZip, please contact vincent@phpconcept.net.
If you can help in financing PhpConcept hosting service, please go to
http://www.phpconcept.net/soutien.php

67
extend/PHPExcel/PHPExcel/Shared/PasswordHasher.php

@ -0,0 +1,67 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Shared_PasswordHasher
*
* @category PHPExcel
* @package PHPExcel_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Shared_PasswordHasher
{
/**
* Create a password hash from a given string.
*
* This method is based on the algorithm provided by
* Daniel Rentz of OpenOffice and the PEAR package
* Spreadsheet_Excel_Writer by Xavier Noguer <xnoguer@rezebra.com>.
*
* @param string $pPassword Password to hash
* @return string Hashed password
*/
public static function hashPassword($pPassword = '')
{
$password = 0x0000;
$charPos = 1; // char position
// split the plain text password in its component characters
$chars = preg_split('//', $pPassword, -1, PREG_SPLIT_NO_EMPTY);
foreach ($chars as $char) {
$value = ord($char) << $charPos++; // shifted ASCII value
$rotated_bits = $value >> 15; // rotated bits beyond bit 15
$value &= 0x7fff; // first 15 bits
$password ^= ($value | $rotated_bits);
}
$password ^= strlen($pPassword);
$password ^= 0xCE4B;
return(strtoupper(dechex($password)));
}
}

819
extend/PHPExcel/PHPExcel/Shared/String.php

@ -0,0 +1,819 @@
<?php
/**
* PHPExcel_Shared_String
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_String
{
/** Constants */
/** Regular Expressions */
// Fraction
const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)';
/**
* Control characters array
*
* @var string[]
*/
private static $controlCharacters = array();
/**
* SYLK Characters array
*
* $var array
*/
private static $SYLKCharacters = array();
/**
* Decimal separator
*
* @var string
*/
private static $decimalSeparator;
/**
* Thousands separator
*
* @var string
*/
private static $thousandsSeparator;
/**
* Currency code
*
* @var string
*/
private static $currencyCode;
/**
* Is mbstring extension avalable?
*
* @var boolean
*/
private static $isMbstringEnabled;
/**
* Is iconv extension avalable?
*
* @var boolean
*/
private static $isIconvEnabled;
/**
* Build control characters array
*/
private static function buildControlCharacters()
{
for ($i = 0; $i <= 31; ++$i) {
if ($i != 9 && $i != 10 && $i != 13) {
$find = '_x' . sprintf('%04s', strtoupper(dechex($i))) . '_';
$replace = chr($i);
self::$controlCharacters[$find] = $replace;
}
}
}
/**
* Build SYLK characters array
*/
private static function buildSYLKCharacters()
{
self::$SYLKCharacters = array(
"\x1B 0" => chr(0),
"\x1B 1" => chr(1),
"\x1B 2" => chr(2),
"\x1B 3" => chr(3),
"\x1B 4" => chr(4),
"\x1B 5" => chr(5),
"\x1B 6" => chr(6),
"\x1B 7" => chr(7),
"\x1B 8" => chr(8),
"\x1B 9" => chr(9),
"\x1B :" => chr(10),
"\x1B ;" => chr(11),
"\x1B <" => chr(12),
"\x1B :" => chr(13),
"\x1B >" => chr(14),
"\x1B ?" => chr(15),
"\x1B!0" => chr(16),
"\x1B!1" => chr(17),
"\x1B!2" => chr(18),
"\x1B!3" => chr(19),
"\x1B!4" => chr(20),
"\x1B!5" => chr(21),
"\x1B!6" => chr(22),
"\x1B!7" => chr(23),
"\x1B!8" => chr(24),
"\x1B!9" => chr(25),
"\x1B!:" => chr(26),
"\x1B!;" => chr(27),
"\x1B!<" => chr(28),
"\x1B!=" => chr(29),
"\x1B!>" => chr(30),
"\x1B!?" => chr(31),
"\x1B'?" => chr(127),
"\x1B(0" => '€', // 128 in CP1252
"\x1B(2" => '‚', // 130 in CP1252
"\x1B(3" => 'ƒ', // 131 in CP1252
"\x1B(4" => '„', // 132 in CP1252
"\x1B(5" => '…', // 133 in CP1252
"\x1B(6" => '†', // 134 in CP1252
"\x1B(7" => '‡', // 135 in CP1252
"\x1B(8" => 'ˆ', // 136 in CP1252
"\x1B(9" => '‰', // 137 in CP1252
"\x1B(:" => 'Š', // 138 in CP1252
"\x1B(;" => '‹', // 139 in CP1252
"\x1BNj" => 'Œ', // 140 in CP1252
"\x1B(>" => 'Ž', // 142 in CP1252
"\x1B)1" => '‘', // 145 in CP1252
"\x1B)2" => '’', // 146 in CP1252
"\x1B)3" => '“', // 147 in CP1252
"\x1B)4" => '”', // 148 in CP1252
"\x1B)5" => '•', // 149 in CP1252
"\x1B)6" => '–', // 150 in CP1252
"\x1B)7" => '—', // 151 in CP1252
"\x1B)8" => '˜', // 152 in CP1252
"\x1B)9" => '™', // 153 in CP1252
"\x1B):" => 'š', // 154 in CP1252
"\x1B);" => '›', // 155 in CP1252
"\x1BNz" => 'œ', // 156 in CP1252
"\x1B)>" => 'ž', // 158 in CP1252
"\x1B)?" => 'Ÿ', // 159 in CP1252
"\x1B*0" => ' ', // 160 in CP1252
"\x1BN!" => '¡', // 161 in CP1252
"\x1BN\"" => '¢', // 162 in CP1252
"\x1BN#" => '£', // 163 in CP1252
"\x1BN(" => '¤', // 164 in CP1252
"\x1BN%" => '¥', // 165 in CP1252
"\x1B*6" => '¦', // 166 in CP1252
"\x1BN'" => '§', // 167 in CP1252
"\x1BNH " => '¨', // 168 in CP1252
"\x1BNS" => '©', // 169 in CP1252
"\x1BNc" => 'ª', // 170 in CP1252
"\x1BN+" => '«', // 171 in CP1252
"\x1B*<" => '¬', // 172 in CP1252
"\x1B*=" => '­', // 173 in CP1252
"\x1BNR" => '®', // 174 in CP1252
"\x1B*?" => '¯', // 175 in CP1252
"\x1BN0" => '°', // 176 in CP1252
"\x1BN1" => '±', // 177 in CP1252
"\x1BN2" => '²', // 178 in CP1252
"\x1BN3" => '³', // 179 in CP1252
"\x1BNB " => '´', // 180 in CP1252
"\x1BN5" => 'µ', // 181 in CP1252
"\x1BN6" => '¶', // 182 in CP1252
"\x1BN7" => '·', // 183 in CP1252
"\x1B+8" => '¸', // 184 in CP1252
"\x1BNQ" => '¹', // 185 in CP1252
"\x1BNk" => 'º', // 186 in CP1252
"\x1BN;" => '»', // 187 in CP1252
"\x1BN<" => '¼', // 188 in CP1252
"\x1BN=" => '½', // 189 in CP1252
"\x1BN>" => '¾', // 190 in CP1252
"\x1BN?" => '¿', // 191 in CP1252
"\x1BNAA" => 'À', // 192 in CP1252
"\x1BNBA" => 'Á', // 193 in CP1252
"\x1BNCA" => 'Â', // 194 in CP1252
"\x1BNDA" => 'Ã', // 195 in CP1252
"\x1BNHA" => 'Ä', // 196 in CP1252
"\x1BNJA" => 'Å', // 197 in CP1252
"\x1BNa" => 'Æ', // 198 in CP1252
"\x1BNKC" => 'Ç', // 199 in CP1252
"\x1BNAE" => 'È', // 200 in CP1252
"\x1BNBE" => 'É', // 201 in CP1252
"\x1BNCE" => 'Ê', // 202 in CP1252
"\x1BNHE" => 'Ë', // 203 in CP1252
"\x1BNAI" => 'Ì', // 204 in CP1252
"\x1BNBI" => 'Í', // 205 in CP1252
"\x1BNCI" => 'Î', // 206 in CP1252
"\x1BNHI" => 'Ï', // 207 in CP1252
"\x1BNb" => 'Ð', // 208 in CP1252
"\x1BNDN" => 'Ñ', // 209 in CP1252
"\x1BNAO" => 'Ò', // 210 in CP1252
"\x1BNBO" => 'Ó', // 211 in CP1252
"\x1BNCO" => 'Ô', // 212 in CP1252
"\x1BNDO" => 'Õ', // 213 in CP1252
"\x1BNHO" => 'Ö', // 214 in CP1252
"\x1B-7" => '×', // 215 in CP1252
"\x1BNi" => 'Ø', // 216 in CP1252
"\x1BNAU" => 'Ù', // 217 in CP1252
"\x1BNBU" => 'Ú', // 218 in CP1252
"\x1BNCU" => 'Û', // 219 in CP1252
"\x1BNHU" => 'Ü', // 220 in CP1252
"\x1B-=" => 'Ý', // 221 in CP1252
"\x1BNl" => 'Þ', // 222 in CP1252
"\x1BN{" => 'ß', // 223 in CP1252
"\x1BNAa" => 'à', // 224 in CP1252
"\x1BNBa" => 'á', // 225 in CP1252
"\x1BNCa" => 'â', // 226 in CP1252
"\x1BNDa" => 'ã', // 227 in CP1252
"\x1BNHa" => 'ä', // 228 in CP1252
"\x1BNJa" => 'å', // 229 in CP1252
"\x1BNq" => 'æ', // 230 in CP1252
"\x1BNKc" => 'ç', // 231 in CP1252
"\x1BNAe" => 'è', // 232 in CP1252
"\x1BNBe" => 'é', // 233 in CP1252
"\x1BNCe" => 'ê', // 234 in CP1252
"\x1BNHe" => 'ë', // 235 in CP1252
"\x1BNAi" => 'ì', // 236 in CP1252
"\x1BNBi" => 'í', // 237 in CP1252
"\x1BNCi" => 'î', // 238 in CP1252
"\x1BNHi" => 'ï', // 239 in CP1252
"\x1BNs" => 'ð', // 240 in CP1252
"\x1BNDn" => 'ñ', // 241 in CP1252
"\x1BNAo" => 'ò', // 242 in CP1252
"\x1BNBo" => 'ó', // 243 in CP1252
"\x1BNCo" => 'ô', // 244 in CP1252
"\x1BNDo" => 'õ', // 245 in CP1252
"\x1BNHo" => 'ö', // 246 in CP1252
"\x1B/7" => '÷', // 247 in CP1252
"\x1BNy" => 'ø', // 248 in CP1252
"\x1BNAu" => 'ù', // 249 in CP1252
"\x1BNBu" => 'ú', // 250 in CP1252
"\x1BNCu" => 'û', // 251 in CP1252
"\x1BNHu" => 'ü', // 252 in CP1252
"\x1B/=" => 'ý', // 253 in CP1252
"\x1BN|" => 'þ', // 254 in CP1252
"\x1BNHy" => 'ÿ', // 255 in CP1252
);
}
/**
* Get whether mbstring extension is available
*
* @return boolean
*/
public static function getIsMbstringEnabled()
{
if (isset(self::$isMbstringEnabled)) {
return self::$isMbstringEnabled;
}
self::$isMbstringEnabled = function_exists('mb_convert_encoding') ?
true : false;
return self::$isMbstringEnabled;
}
/**
* Get whether iconv extension is available
*
* @return boolean
*/
public static function getIsIconvEnabled()
{
if (isset(self::$isIconvEnabled)) {
return self::$isIconvEnabled;
}
// Fail if iconv doesn't exist
if (!function_exists('iconv')) {
self::$isIconvEnabled = false;
return false;
}
// Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false,
if (!@iconv('UTF-8', 'UTF-16LE', 'x')) {
self::$isIconvEnabled = false;
return false;
}
// 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 (!@iconv_substr('A', 0, 1, 'UTF-8')) {
self::$isIconvEnabled = false;
return false;
}
// CUSTOM: IBM AIX iconv() does not work
if (defined('PHP_OS') && @stristr(PHP_OS, 'AIX') && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0)) {
self::$isIconvEnabled = false;
return false;
}
// If we reach here no problems were detected with iconv
self::$isIconvEnabled = true;
return true;
}
public static function buildCharacterSets()
{
if (empty(self::$controlCharacters)) {
self::buildControlCharacters();
}
if (empty(self::$SYLKCharacters)) {
self::buildSYLKCharacters();
}
}
/**
* Convert from OpenXML escaped control character to PHP control character
*
* Excel 2007 team:
* ----------------
* That's correct, control characters are stored directly in the shared-strings table.
* We do encode characters that cannot be represented in XML using the following escape sequence:
* _xHHHH_ where H represents a hexadecimal character in the character's value...
* So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
* element or in the shared string <t> element.
*
* @param string $value Value to unescape
* @return string
*/
public static function ControlCharacterOOXML2PHP($value = '')
{
return str_replace(array_keys(self::$controlCharacters), array_values(self::$controlCharacters), $value);
}
/**
* Convert from PHP control character to OpenXML escaped control character
*
* Excel 2007 team:
* ----------------
* That's correct, control characters are stored directly in the shared-strings table.
* We do encode characters that cannot be represented in XML using the following escape sequence:
* _xHHHH_ where H represents a hexadecimal character in the character's value...
* So you could end up with something like _x0008_ in a string (either in a cell value (<v>)
* element or in the shared string <t> element.
*
* @param string $value Value to escape
* @return string
*/
public static function ControlCharacterPHP2OOXML($value = '')
{
return str_replace(array_values(self::$controlCharacters), array_keys(self::$controlCharacters), $value);
}
/**
* Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters.
*
* @param string $value
* @return string
*/
public static function SanitizeUTF8($value)
{
if (self::getIsIconvEnabled()) {
$value = @iconv('UTF-8', 'UTF-8', $value);
return $value;
}
if (self::getIsMbstringEnabled()) {
$value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
return $value;
}
// else, no conversion
return $value;
}
/**
* Check if a string contains UTF8 data
*
* @param string $value
* @return boolean
*/
public static function IsUTF8($value = '')
{
return $value === '' || preg_match('/^./su', $value) === 1;
}
/**
* Formats a numeric value as a string for output in various output writers forcing
* point as decimal separator in case locale is other than English.
*
* @param mixed $value
* @return string
*/
public static function FormatNumber($value)
{
if (is_float($value)) {
return str_replace(',', '.', $value);
}
return (string) $value;
}
/**
* Converts a UTF-8 string into BIFF8 Unicode string data (8-bit string length)
* Writes the string using uncompressed notation, no rich text, no Asian phonetics
* If mbstring extension is not available, ASCII is assumed, and compressed notation is used
* although this will give wrong results for non-ASCII strings
* see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3
*
* @param string $value UTF-8 encoded string
* @param mixed[] $arrcRuns Details of rich text runs in $value
* @return string
*/
public static function UTF8toBIFF8UnicodeShort($value, $arrcRuns = array())
{
// character count
$ln = self::CountCharacters($value, 'UTF-8');
// option flags
if (empty($arrcRuns)) {
$opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ?
0x0001 : 0x0000;
$data = pack('CC', $ln, $opt);
// characters
$data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8');
} else {
$data = pack('vC', $ln, 0x09);
$data .= pack('v', count($arrcRuns));
// characters
$data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8');
foreach ($arrcRuns as $cRun) {
$data .= pack('v', $cRun['strlen']);
$data .= pack('v', $cRun['fontidx']);
}
}
return $data;
}
/**
* Converts a UTF-8 string into BIFF8 Unicode string data (16-bit string length)
* Writes the string using uncompressed notation, no rich text, no Asian phonetics
* If mbstring extension is not available, ASCII is assumed, and compressed notation is used
* although this will give wrong results for non-ASCII strings
* see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3
*
* @param string $value UTF-8 encoded string
* @return string
*/
public static function UTF8toBIFF8UnicodeLong($value)
{
// character count
$ln = self::CountCharacters($value, 'UTF-8');
// option flags
$opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ?
0x0001 : 0x0000;
// characters
$chars = self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8');
$data = pack('vC', $ln, $opt) . $chars;
return $data;
}
/**
* Convert string from one encoding to another. First try mbstring, then iconv, finally strlen
*
* @param string $value
* @param string $to Encoding to convert to, e.g. 'UTF-8'
* @param string $from Encoding to convert from, e.g. 'UTF-16LE'
* @return string
*/
public static function ConvertEncoding($value, $to, $from)
{
if (self::getIsIconvEnabled()) {
return iconv($from, $to, $value);
}
if (self::getIsMbstringEnabled()) {
return mb_convert_encoding($value, $to, $from);
}
if ($from == 'UTF-16LE') {
return self::utf16_decode($value, false);
} elseif ($from == 'UTF-16BE') {
return self::utf16_decode($value);
}
// else, no conversion
return $value;
}
/**
* Decode UTF-16 encoded strings.
*
* Can handle both BOM'ed data and un-BOM'ed data.
* Assumes Big-Endian byte order if no BOM is available.
* This function was taken from http://php.net/manual/en/function.utf8-decode.php
* and $bom_be parameter added.
*
* @param string $str UTF-16 encoded data to decode.
* @return string UTF-8 / ISO encoded data.
* @access public
* @version 0.2 / 2010-05-13
* @author Rasmus Andersson {@link http://rasmusandersson.se/}
* @author vadik56
*/
public static function utf16_decode($str, $bom_be = true)
{
if (strlen($str) < 2) {
return $str;
}
$c0 = ord($str{0});
$c1 = ord($str{1});
if ($c0 == 0xfe && $c1 == 0xff) {
$str = substr($str, 2);
} elseif ($c0 == 0xff && $c1 == 0xfe) {
$str = substr($str, 2);
$bom_be = false;
}
$len = strlen($str);
$newstr = '';
for ($i=0; $i<$len; $i+=2) {
if ($bom_be) {
$val = ord($str{$i}) << 4;
$val += ord($str{$i+1});
} else {
$val = ord($str{$i+1}) << 4;
$val += ord($str{$i});
}
$newstr .= ($val == 0x228) ? "\n" : chr($val);
}
return $newstr;
}
/**
* Get character count. First try mbstring, then iconv, finally strlen
*
* @param string $value
* @param string $enc Encoding
* @return int Character count
*/
public static function CountCharacters($value, $enc = 'UTF-8')
{
if (self::getIsMbstringEnabled()) {
return mb_strlen($value, $enc);
}
if (self::getIsIconvEnabled()) {
return iconv_strlen($value, $enc);
}
// else strlen
return strlen($value);
}
/**
* Get a substring of a UTF-8 encoded string. First try mbstring, then iconv, finally strlen
*
* @param string $pValue UTF-8 encoded string
* @param int $pStart Start offset
* @param int $pLength Maximum number of characters in substring
* @return string
*/
public static function Substring($pValue = '', $pStart = 0, $pLength = 0)
{
if (self::getIsMbstringEnabled()) {
return mb_substr($pValue, $pStart, $pLength, 'UTF-8');
}
if (self::getIsIconvEnabled()) {
return iconv_substr($pValue, $pStart, $pLength, 'UTF-8');
}
// else substr
return substr($pValue, $pStart, $pLength);
}
/**
* Convert a UTF-8 encoded string to upper case
*
* @param string $pValue UTF-8 encoded string
* @return string
*/
public static function StrToUpper($pValue = '')
{
if (function_exists('mb_convert_case')) {
return mb_convert_case($pValue, MB_CASE_UPPER, "UTF-8");
}
return strtoupper($pValue);
}
/**
* Convert a UTF-8 encoded string to lower case
*
* @param string $pValue UTF-8 encoded string
* @return string
*/
public static function StrToLower($pValue = '')
{
if (function_exists('mb_convert_case')) {
return mb_convert_case($pValue, MB_CASE_LOWER, "UTF-8");
}
return strtolower($pValue);
}
/**
* Convert a UTF-8 encoded string to title/proper case
* (uppercase every first character in each word, lower case all other characters)
*
* @param string $pValue UTF-8 encoded string
* @return string
*/
public static function StrToTitle($pValue = '')
{
if (function_exists('mb_convert_case')) {
return mb_convert_case($pValue, MB_CASE_TITLE, "UTF-8");
}
return ucwords($pValue);
}
public static function mb_is_upper($char)
{
return mb_strtolower($char, "UTF-8") != $char;
}
public static function mb_str_split($string)
{
# Split at all position not after the start: ^
# and not before the end: $
return preg_split('/(?<!^)(?!$)/u', $string);
}
/**
* Reverse the case of a string, so that all uppercase characters become lowercase
* and all lowercase characters become uppercase
*
* @param string $pValue UTF-8 encoded string
* @return string
*/
public static function StrCaseReverse($pValue = '')
{
if (self::getIsMbstringEnabled()) {
$characters = self::mb_str_split($pValue);
foreach ($characters as &$character) {
if (self::mb_is_upper($character)) {
$character = mb_strtolower($character, 'UTF-8');
} else {
$character = mb_strtoupper($character, 'UTF-8');
}
}
return implode('', $characters);
}
return strtolower($pValue) ^ strtoupper($pValue) ^ $pValue;
}
/**
* 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'];
if (self::$thousandsSeparator == '') {
// Default to .
self::$thousandsSeparator = ',';
}
}
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;
}
/**
* Get the currency code. If it has not yet been set explicitly, try to obtain the
* symbol information from locale.
*
* @return string
*/
public static function getCurrencyCode()
{
if (!isset(self::$currencyCode)) {
$localeconv = localeconv();
self::$currencyCode = ($localeconv['currency_symbol'] != '')
? $localeconv['currency_symbol'] : $localeconv['int_curr_symbol'];
if (self::$currencyCode == '') {
// Default to $
self::$currencyCode = '$';
}
}
return self::$currencyCode;
}
/**
* Set the currency code. Only used by PHPExcel_Style_NumberFormat::toFormattedString()
* to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF
*
* @param string $pValue Character for currency code
*/
public static function setCurrencyCode($pValue = '$')
{
self::$currencyCode = $pValue;
}
/**
* Convert SYLK encoded string to UTF-8
*
* @param string $pValue
* @return string UTF-8 encoded string
*/
public static function SYLKtoUTF8($pValue = '')
{
// If there is no escape character in the string there is nothing to do
if (strpos($pValue, '') === false) {
return $pValue;
}
foreach (self::$SYLKCharacters as $k => $v) {
$pValue = str_replace($k, $v, $pValue);
}
return $pValue;
}
/**
* Retrieve any leading numeric part of a string, or return the full string if no leading numeric
* (handles basic integer or float, but not exponent or non decimal)
*
* @param string $value
* @return mixed string or only the leading numeric part of the string
*/
public static function testStringAsNumeric($value)
{
if (is_numeric($value)) {
return $value;
}
$v = floatval($value);
return (is_numeric(substr($value, 0, strlen($v)))) ? $v : $value;
}
}

144
extend/PHPExcel/PHPExcel/Shared/TimeZone.php

@ -0,0 +1,144 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Shared_TimeZone
*
* @category PHPExcel
* @package PHPExcel_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Shared_TimeZone
{
/*
* Default Timezone used for date/time conversions
*
* @private
* @var string
*/
protected static $timezone = 'UTC';
/**
* Validate a Timezone name
*
* @param string $timezone Time zone (e.g. 'Europe/London')
* @return boolean Success or failure
*/
public static function _validateTimeZone($timezone)
{
if (in_array($timezone, DateTimeZone::listIdentifiers())) {
return true;
}
return false;
}
/**
* Set the Default Timezone used for date/time conversions
*
* @param string $timezone Time zone (e.g. 'Europe/London')
* @return boolean Success or failure
*/
public static function setTimeZone($timezone)
{
if (self::_validateTimezone($timezone)) {
self::$timezone = $timezone;
return true;
}
return false;
}
/**
* Return the Default Timezone used for date/time conversions
*
* @return string Timezone (e.g. 'Europe/London')
*/
public static function getTimeZone()
{
return self::$timezone;
}
/**
* Return the Timezone transition for the specified timezone and timestamp
*
* @param DateTimeZone $objTimezone The timezone for finding the transitions
* @param integer $timestamp PHP date/time value for finding the current transition
* @return array The current transition details
*/
private static function getTimezoneTransitions($objTimezone, $timestamp)
{
$allTransitions = $objTimezone->getTransitions();
$transitions = array();
foreach ($allTransitions as $key => $transition) {
if ($transition['ts'] > $timestamp) {
$transitions[] = ($key > 0) ? $allTransitions[$key - 1] : $transition;
break;
}
if (empty($transitions)) {
$transitions[] = end($allTransitions);
}
}
return $transitions;
}
/**
* Return the Timezone offset used for date/time conversions to/from UST
* This requires both the timezone and the calculated date/time to allow for local DST
*
* @param string $timezone The timezone for finding the adjustment to UST
* @param integer $timestamp PHP date/time value
* @return integer Number of seconds for timezone adjustment
* @throws PHPExcel_Exception
*/
public static function getTimeZoneAdjustment($timezone, $timestamp)
{
if ($timezone !== null) {
if (!self::_validateTimezone($timezone)) {
throw new PHPExcel_Exception("Invalid timezone " . $timezone);
}
} else {
$timezone = self::$timezone;
}
if ($timezone == 'UST') {
return 0;
}
$objTimezone = new DateTimeZone($timezone);
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
$transitions = $objTimezone->getTransitions($timestamp, $timestamp);
} else {
$transitions = self::getTimezoneTransitions($objTimezone, $timestamp);
}
return (count($transitions) > 0) ? $transitions[0]['offset'] : 0;
}
}

124
extend/PHPExcel/PHPExcel/Shared/XMLWriter.php

@ -0,0 +1,124 @@
<?php
if (!defined('DATE_W3C')) {
define('DATE_W3C', 'Y-m-d\TH:i:sP');
}
if (!defined('DEBUGMODE_ENABLED')) {
define('DEBUGMODE_ENABLED', false);
}
/**
* PHPExcel_Shared_XMLWriter
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_XMLWriter extends XMLWriter
{
/** Temporary storage method */
const STORAGE_MEMORY = 1;
const STORAGE_DISK = 2;
/**
* Temporary filename
*
* @var string
*/
private $tempFileName = '';
/**
* Create a new PHPExcel_Shared_XMLWriter instance
*
* @param int $pTemporaryStorage Temporary storage location
* @param string $pTemporaryStorageFolder Temporary storage folder
*/
public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTemporaryStorageFolder = null)
{
// Open temporary storage
if ($pTemporaryStorage == self::STORAGE_MEMORY) {
$this->openMemory();
} else {
// Create temporary filename
if ($pTemporaryStorageFolder === null) {
$pTemporaryStorageFolder = PHPExcel_Shared_File::sys_get_temp_dir();
}
$this->tempFileName = @tempnam($pTemporaryStorageFolder, 'xml');
// Open storage
if ($this->openUri($this->tempFileName) === false) {
// Fallback to memory...
$this->openMemory();
}
}
// Set default values
if (DEBUGMODE_ENABLED) {
$this->setIndent(true);
}
}
/**
* Destructor
*/
public function __destruct()
{
// Unlink temporary files
if ($this->tempFileName != '') {
@unlink($this->tempFileName);
}
}
/**
* Get written data
*
* @return $data
*/
public function getData()
{
if ($this->tempFileName == '') {
return $this->outputMemory(true);
} else {
$this->flush();
return file_get_contents($this->tempFileName);
}
}
/**
* Fallback method for writeRaw, introduced in PHP 5.2
*
* @param string $text
* @return string
*/
public function writeRawData($text)
{
if (is_array($text)) {
$text = implode("\n", $text);
}
if (method_exists($this, 'writeRaw')) {
return $this->writeRaw(htmlspecialchars($text));
}
return $this->text($text);
}
}

163
extend/PHPExcel/PHPExcel/Shared/ZipArchive.php

@ -0,0 +1,163 @@
<?php
if (!defined('PCLZIP_TEMPORARY_DIR')) {
define('PCLZIP_TEMPORARY_DIR', PHPExcel_Shared_File::sys_get_temp_dir() . DIRECTORY_SEPARATOR);
}
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PCLZip/pclzip.lib.php';
/**
* PHPExcel_Shared_ZipArchive
*
* Copyright (c) 2006 - 2015 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_Shared_ZipArchive
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_ZipArchive
{
/** constants */
const OVERWRITE = 'OVERWRITE';
const CREATE = 'CREATE';
/**
* Temporary storage directory
*
* @var string
*/
private $tempDir;
/**
* Zip Archive Stream Handle
*
* @var string
*/
private $zip;
/**
* Open a new zip archive
*
* @param string $fileName Filename for the zip archive
* @return boolean
*/
public function open($fileName)
{
$this->tempDir = PHPExcel_Shared_File::sys_get_temp_dir();
$this->zip = new PclZip($fileName);
return true;
}
/**
* Close this zip archive
*
*/
public function close()
{
}
/**
* Add a new file to the zip archive from a string of raw data.
*
* @param string $localname Directory/Name of the file to add to the zip archive
* @param string $contents String of data to add to the zip archive
*/
public function addFromString($localname, $contents)
{
$filenameParts = pathinfo($localname);
$handle = fopen($this->tempDir.'/'.$filenameParts["basename"], "wb");
fwrite($handle, $contents);
fclose($handle);
$res = $this->zip->add($this->tempDir.'/'.$filenameParts["basename"], PCLZIP_OPT_REMOVE_PATH, $this->tempDir, PCLZIP_OPT_ADD_PATH, $filenameParts["dirname"]);
if ($res == 0) {
throw new PHPExcel_Writer_Exception("Error zipping files : " . $this->zip->errorInfo(true));
}
unlink($this->tempDir.'/'.$filenameParts["basename"]);
}
/**
* Find if given fileName exist in archive (Emulate ZipArchive locateName())
*
* @param string $fileName Filename for the file in zip archive
* @return boolean
*/
public function locateName($fileName)
{
$fileName = strtolower($fileName);
$list = $this->zip->listContent();
$listCount = count($list);
$index = -1;
for ($i = 0; $i < $listCount; ++$i) {
if (strtolower($list[$i]["filename"]) == $fileName ||
strtolower($list[$i]["stored_filename"]) == $fileName) {
$index = $i;
break;
}
}
return ($index > -1) ? $index : false;
}
/**
* Extract file from archive by given fileName (Emulate ZipArchive getFromName())
*
* @param string $fileName Filename for the file in zip archive
* @return string $contents File string contents
*/
public function getFromName($fileName)
{
$index = $this->locateName($fileName);
if ($index !== false) {
$extracted = $this->getFromIndex($index);
} else {
$fileName = substr($fileName, 1);
$index = $this->locateName($fileName);
if ($index === false) {
return false;
}
$extracted = $this->zip->getFromIndex($index);
}
$contents = $extracted;
if ((is_array($extracted)) && ($extracted != 0)) {
$contents = $extracted[0]["content"];
}
return $contents;
}
public function getFromIndex($index) {
$extracted = $this->zip->extractByIndex($index, PCLZIP_OPT_EXTRACT_AS_STRING);
$contents = '';
if ((is_array($extracted)) && ($extracted != 0)) {
$contents = $extracted[0]["content"];
}
return $contents;
}
}

200
extend/PHPExcel/PHPExcel/Shared/ZipStreamWrapper.php

@ -0,0 +1,200 @@
<?php
/**
* PHPExcel_Shared_ZipStreamWrapper
*
* Copyright (c) 2006 - 2015 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_Shared
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Shared_ZipStreamWrapper
{
/**
* Internal ZipAcrhive
*
* @var ZipArchive
*/
private $archive;
/**
* Filename in ZipAcrhive
*
* @var string
*/
private $fileNameInArchive = '';
/**
* Position in file
*
* @var int
*/
private $position = 0;
/**
* Data
*
* @var mixed
*/
private $data = '';
/**
* Register wrapper
*/
public static function register()
{
@stream_wrapper_unregister('zip');
@stream_wrapper_register('zip', __CLASS__);
}
/**
* Implements support for fopen().
*
* @param string $path resource name including scheme, e.g.
* @param string $mode only "r" is supported
* @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH
* @param string &$openedPath absolute path of the opened stream (out parameter)
* @return bool true on success
*/
public function stream_open($path, $mode, $options, &$opened_path)
{
// Check for mode
if ($mode{0} != 'r') {
throw new PHPExcel_Reader_Exception('Mode ' . $mode . ' is not supported. Only read mode is supported.');
}
$pos = strrpos($path, '#');
$url['host'] = substr($path, 6, $pos - 6); // 6: strlen('zip://')
$url['fragment'] = substr($path, $pos + 1);
// Open archive
$this->archive = new ZipArchive();
$this->archive->open($url['host']);
$this->fileNameInArchive = $url['fragment'];
$this->position = 0;
$this->data = $this->archive->getFromName($this->fileNameInArchive);
return true;
}
/**
* Implements support for fstat().
*
* @return boolean
*/
public function statName()
{
return $this->fileNameInArchive;
}
/**
* Implements support for fstat().
*
* @return boolean
*/
public function url_stat()
{
return $this->statName($this->fileNameInArchive);
}
/**
* Implements support for fstat().
*
* @return boolean
*/
public function stream_stat()
{
return $this->archive->statName($this->fileNameInArchive);
}
/**
* Implements support for fread(), fgets() etc.
*
* @param int $count maximum number of bytes to read
* @return string
*/
public function stream_read($count)
{
$ret = substr($this->data, $this->position, $count);
$this->position += strlen($ret);
return $ret;
}
/**
* Returns the position of the file pointer, i.e. its offset into the file
* stream. Implements support for ftell().
*
* @return int
*/
public function stream_tell()
{
return $this->position;
}
/**
* EOF stream
*
* @return bool
*/
public function stream_eof()
{
return $this->position >= strlen($this->data);
}
/**
* Seek stream
*
* @param int $offset byte offset
* @param int $whence SEEK_SET, SEEK_CUR or SEEK_END
* @return bool
*/
public function stream_seek($offset, $whence)
{
switch ($whence) {
case SEEK_SET:
if ($offset < strlen($this->data) && $offset >= 0) {
$this->position = $offset;
return true;
} else {
return false;
}
break;
case SEEK_CUR:
if ($offset >= 0) {
$this->position += $offset;
return true;
} else {
return false;
}
break;
case SEEK_END:
if (strlen($this->data) + $offset >= 0) {
$this->position = strlen($this->data) + $offset;
return true;
} else {
return false;
}
break;
default:
return false;
}
}
}

425
extend/PHPExcel/PHPExcel/Shared/trend/bestFitClass.php

@ -0,0 +1,425 @@
<?php
/**
* PHPExcel_Best_Fit
*
* Copyright (c) 2006 - 2015 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_Shared_Trend
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Best_Fit
{
/**
* Indicator flag for a calculation error
*
* @var boolean
**/
protected $error = false;
/**
* Algorithm type to use for best-fit
*
* @var string
**/
protected $bestFitType = 'undetermined';
/**
* Number of entries in the sets of x- and y-value arrays
*
* @var int
**/
protected $valueCount = 0;
/**
* X-value dataseries of values
*
* @var float[]
**/
protected $xValues = array();
/**
* Y-value dataseries of values
*
* @var float[]
**/
protected $yValues = array();
/**
* Flag indicating whether values should be adjusted to Y=0
*
* @var boolean
**/
protected $adjustToZero = false;
/**
* Y-value series of best-fit values
*
* @var float[]
**/
protected $yBestFitValues = array();
protected $goodnessOfFit = 1;
protected $stdevOfResiduals = 0;
protected $covariance = 0;
protected $correlation = 0;
protected $SSRegression = 0;
protected $SSResiduals = 0;
protected $DFResiduals = 0;
protected $f = 0;
protected $slope = 0;
protected $slopeSE = 0;
protected $intersect = 0;
protected $intersectSE = 0;
protected $xOffset = 0;
protected $yOffset = 0;
public function getError()
{
return $this->error;
}
public function getBestFitType()
{
return $this->bestFitType;
}
/**
* Return the Y-Value for a specified value of X
*
* @param float $xValue X-Value
* @return float Y-Value
*/
public function getValueOfYForX($xValue)
{
return false;
}
/**
* Return the X-Value for a specified value of Y
*
* @param float $yValue Y-Value
* @return float X-Value
*/
public function getValueOfXForY($yValue)
{
return false;
}
/**
* Return the original set of X-Values
*
* @return float[] X-Values
*/
public function getXValues()
{
return $this->xValues;
}
/**
* Return the Equation of the best-fit line
*
* @param int $dp Number of places of decimal precision to display
* @return string
*/
public function getEquation($dp = 0)
{
return false;
}
/**
* Return the Slope of the line
*
* @param int $dp Number of places of decimal precision to display
* @return string
*/
public function getSlope($dp = 0)
{
if ($dp != 0) {
return round($this->slope, $dp);
}
return $this->slope;
}
/**
* Return the standard error of the Slope
*
* @param int $dp Number of places of decimal precision to display
* @return string
*/
public function getSlopeSE($dp = 0)
{
if ($dp != 0) {
return round($this->slopeSE, $dp);
}
return $this->slopeSE;
}
/**
* Return the Value of X where it intersects Y = 0
*
* @param int $dp Number of places of decimal precision to display
* @return string
*/
public function getIntersect($dp = 0)
{
if ($dp != 0) {
return round($this->intersect, $dp);
}
return $this->intersect;
}
/**
* Return the standard error of the Intersect
*
* @param int $dp Number of places of decimal precision to display
* @return string
*/
public function getIntersectSE($dp = 0)
{
if ($dp != 0) {
return round($this->intersectSE, $dp);
}
return $this->intersectSE;
}
/**
* Return the goodness of fit for this regression
*
* @param int $dp Number of places of decimal precision to return
* @return float
*/
public function getGoodnessOfFit($dp = 0)
{
if ($dp != 0) {
return round($this->goodnessOfFit, $dp);
}
return $this->goodnessOfFit;
}
public function getGoodnessOfFitPercent($dp = 0)
{
if ($dp != 0) {
return round($this->goodnessOfFit * 100, $dp);
}
return $this->goodnessOfFit * 100;
}
/**
* Return the standard deviation of the residuals for this regression
*
* @param int $dp Number of places of decimal precision to return
* @return float
*/
public function getStdevOfResiduals($dp = 0)
{
if ($dp != 0) {
return round($this->stdevOfResiduals, $dp);
}
return $this->stdevOfResiduals;
}
public function getSSRegression($dp = 0)
{
if ($dp != 0) {
return round($this->SSRegression, $dp);
}
return $this->SSRegression;
}
public function getSSResiduals($dp = 0)
{
if ($dp != 0) {
return round($this->SSResiduals, $dp);
}
return $this->SSResiduals;
}
public function getDFResiduals($dp = 0)
{
if ($dp != 0) {
return round($this->DFResiduals, $dp);
}
return $this->DFResiduals;
}
public function getF($dp = 0)
{
if ($dp != 0) {
return round($this->f, $dp);
}
return $this->f;
}
public function getCovariance($dp = 0)
{
if ($dp != 0) {
return round($this->covariance, $dp);
}
return $this->covariance;
}
public function getCorrelation($dp = 0)
{
if ($dp != 0) {
return round($this->correlation, $dp);
}
return $this->correlation;
}
public function getYBestFitValues()
{
return $this->yBestFitValues;
}
protected function calculateGoodnessOfFit($sumX, $sumY, $sumX2, $sumY2, $sumXY, $meanX, $meanY, $const)
{
$SSres = $SScov = $SScor = $SStot = $SSsex = 0.0;
foreach ($this->xValues as $xKey => $xValue) {
$bestFitY = $this->yBestFitValues[$xKey] = $this->getValueOfYForX($xValue);
$SSres += ($this->yValues[$xKey] - $bestFitY) * ($this->yValues[$xKey] - $bestFitY);
if ($const) {
$SStot += ($this->yValues[$xKey] - $meanY) * ($this->yValues[$xKey] - $meanY);
} else {
$SStot += $this->yValues[$xKey] * $this->yValues[$xKey];
}
$SScov += ($this->xValues[$xKey] - $meanX) * ($this->yValues[$xKey] - $meanY);
if ($const) {
$SSsex += ($this->xValues[$xKey] - $meanX) * ($this->xValues[$xKey] - $meanX);
} else {
$SSsex += $this->xValues[$xKey] * $this->xValues[$xKey];
}
}
$this->SSResiduals = $SSres;
$this->DFResiduals = $this->valueCount - 1 - $const;
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 {
$this->goodnessOfFit = 1 - ($SSres / $SStot);
}
$this->SSRegression = $this->goodnessOfFit * $SStot;
$this->covariance = $SScov / $this->valueCount;
$this->correlation = ($this->valueCount * $sumXY - $sumX * $sumY) / sqrt(($this->valueCount * $sumX2 - pow($sumX, 2)) * ($this->valueCount * $sumY2 - pow($sumY, 2)));
$this->slopeSE = $this->stdevOfResiduals / sqrt($SSsex);
$this->intersectSE = $this->stdevOfResiduals * sqrt(1 / ($this->valueCount - ($sumX * $sumX) / $sumX2));
if ($this->SSResiduals != 0.0) {
if ($this->DFResiduals == 0.0) {
$this->f = 0.0;
} else {
$this->f = $this->SSRegression / ($this->SSResiduals / $this->DFResiduals);
}
} else {
if ($this->DFResiduals == 0.0) {
$this->f = 0.0;
} else {
$this->f = $this->SSRegression / $this->DFResiduals;
}
}
}
protected function leastSquareFit($yValues, $xValues, $const)
{
// calculate sums
$x_sum = array_sum($xValues);
$y_sum = array_sum($yValues);
$meanX = $x_sum / $this->valueCount;
$meanY = $y_sum / $this->valueCount;
$mBase = $mDivisor = $xx_sum = $xy_sum = $yy_sum = 0.0;
for ($i = 0; $i < $this->valueCount; ++$i) {
$xy_sum += $xValues[$i] * $yValues[$i];
$xx_sum += $xValues[$i] * $xValues[$i];
$yy_sum += $yValues[$i] * $yValues[$i];
if ($const) {
$mBase += ($xValues[$i] - $meanX) * ($yValues[$i] - $meanY);
$mDivisor += ($xValues[$i] - $meanX) * ($xValues[$i] - $meanX);
} else {
$mBase += $xValues[$i] * $yValues[$i];
$mDivisor += $xValues[$i] * $xValues[$i];
}
}
// calculate slope
// $this->slope = (($this->valueCount * $xy_sum) - ($x_sum * $y_sum)) / (($this->valueCount * $xx_sum) - ($x_sum * $x_sum));
$this->slope = $mBase / $mDivisor;
// calculate intersect
// $this->intersect = ($y_sum - ($this->slope * $x_sum)) / $this->valueCount;
if ($const) {
$this->intersect = $meanY - ($this->slope * $meanX);
} else {
$this->intersect = 0;
}
$this->calculateGoodnessOfFit($x_sum, $y_sum, $xx_sum, $yy_sum, $xy_sum, $meanX, $meanY, $const);
}
/**
* Define the regression
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
public function __construct($yValues, $xValues = array(), $const = true)
{
// Calculate number of points
$nY = count($yValues);
$nX = count($xValues);
// Define X Values if necessary
if ($nX == 0) {
$xValues = range(1, $nY);
$nX = $nY;
} elseif ($nY != $nX) {
// Ensure both arrays of points are the same size
$this->error = true;
return false;
}
$this->valueCount = $nY;
$this->xValues = $xValues;
$this->yValues = $yValues;
}
}

138
extend/PHPExcel/PHPExcel/Shared/trend/exponentialBestFitClass.php

@ -0,0 +1,138 @@
<?php
require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php');
/**
* PHPExcel_Exponential_Best_Fit
*
* Copyright (c) 2006 - 2015 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_Shared_Trend
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit
{
/**
* Algorithm type to use for best-fit
* (Name of this trend class)
*
* @var string
**/
protected $bestFitType = 'exponential';
/**
* Return the Y-Value for a specified value of X
*
* @param float $xValue X-Value
* @return float Y-Value
**/
public function getValueOfYForX($xValue)
{
return $this->getIntersect() * pow($this->getSlope(), ($xValue - $this->xOffset));
}
/**
* Return the X-Value for a specified value of Y
*
* @param float $yValue Y-Value
* @return float X-Value
**/
public function getValueOfXForY($yValue)
{
return log(($yValue + $this->yOffset) / $this->getIntersect()) / log($this->getSlope());
}
/**
* Return the Equation of the best-fit line
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getEquation($dp = 0)
{
$slope = $this->getSlope($dp);
$intersect = $this->getIntersect($dp);
return 'Y = ' . $intersect . ' * ' . $slope . '^X';
}
/**
* Return the Slope of the line
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getSlope($dp = 0)
{
if ($dp != 0) {
return round(exp($this->_slope), $dp);
}
return exp($this->_slope);
}
/**
* Return the Value of X where it intersects Y = 0
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getIntersect($dp = 0)
{
if ($dp != 0) {
return round(exp($this->intersect), $dp);
}
return exp($this->intersect);
}
/**
* Execute the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
private function exponentialRegression($yValues, $xValues, $const)
{
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);
}
/**
* Define the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
public function __construct($yValues, $xValues = array(), $const = true)
{
if (parent::__construct($yValues, $xValues) !== false) {
$this->exponentialRegression($yValues, $xValues, $const);
}
}
}

102
extend/PHPExcel/PHPExcel/Shared/trend/linearBestFitClass.php

@ -0,0 +1,102 @@
<?php
require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php');
/**
* PHPExcel_Linear_Best_Fit
*
* Copyright (c) 2006 - 2015 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_Shared_Trend
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Linear_Best_Fit extends PHPExcel_Best_Fit
{
/**
* Algorithm type to use for best-fit
* (Name of this trend class)
*
* @var string
**/
protected $bestFitType = 'linear';
/**
* Return the Y-Value for a specified value of X
*
* @param float $xValue X-Value
* @return float Y-Value
**/
public function getValueOfYForX($xValue)
{
return $this->getIntersect() + $this->getSlope() * $xValue;
}
/**
* Return the X-Value for a specified value of Y
*
* @param float $yValue Y-Value
* @return float X-Value
**/
public function getValueOfXForY($yValue)
{
return ($yValue - $this->getIntersect()) / $this->getSlope();
}
/**
* Return the Equation of the best-fit line
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getEquation($dp = 0)
{
$slope = $this->getSlope($dp);
$intersect = $this->getIntersect($dp);
return 'Y = ' . $intersect . ' + ' . $slope . ' * X';
}
/**
* Execute the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
private function linearRegression($yValues, $xValues, $const)
{
$this->leastSquareFit($yValues, $xValues, $const);
}
/**
* Define the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
public function __construct($yValues, $xValues = array(), $const = true)
{
if (parent::__construct($yValues, $xValues) !== false) {
$this->linearRegression($yValues, $xValues, $const);
}
}
}

110
extend/PHPExcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php

@ -0,0 +1,110 @@
<?php
require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php');
/**
* PHPExcel_Logarithmic_Best_Fit
*
* Copyright (c) 2006 - 2015 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_Shared_Trend
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit
{
/**
* Algorithm type to use for best-fit
* (Name of this trend class)
*
* @var string
**/
protected $bestFitType = 'logarithmic';
/**
* Return the Y-Value for a specified value of X
*
* @param float $xValue X-Value
* @return float Y-Value
**/
public function getValueOfYForX($xValue)
{
return $this->getIntersect() + $this->getSlope() * log($xValue - $this->xOffset);
}
/**
* Return the X-Value for a specified value of Y
*
* @param float $yValue Y-Value
* @return float X-Value
**/
public function getValueOfXForY($yValue)
{
return exp(($yValue - $this->getIntersect()) / $this->getSlope());
}
/**
* Return the Equation of the best-fit line
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getEquation($dp = 0)
{
$slope = $this->getSlope($dp);
$intersect = $this->getIntersect($dp);
return 'Y = '.$intersect.' + '.$slope.' * log(X)';
}
/**
* Execute the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
private function logarithmicRegression($yValues, $xValues, $const)
{
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);
}
/**
* Define the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
public function __construct($yValues, $xValues = array(), $const = true)
{
if (parent::__construct($yValues, $xValues) !== false) {
$this->logarithmicRegression($yValues, $xValues, $const);
}
}
}

222
extend/PHPExcel/PHPExcel/Shared/trend/polynomialBestFitClass.php

@ -0,0 +1,222 @@
<?php
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php';
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php';
/**
* PHPExcel_Polynomial_Best_Fit
*
* Copyright (c) 2006 - 2015 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_Shared_Trend
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Polynomial_Best_Fit extends PHPExcel_Best_Fit
{
/**
* Algorithm type to use for best-fit
* (Name of this trend class)
*
* @var string
**/
protected $bestFitType = 'polynomial';
/**
* Polynomial order
*
* @protected
* @var int
**/
protected $order = 0;
/**
* Return the order of this polynomial
*
* @return int
**/
public function getOrder()
{
return $this->order;
}
/**
* Return the Y-Value for a specified value of X
*
* @param float $xValue X-Value
* @return float Y-Value
**/
public function getValueOfYForX($xValue)
{
$retVal = $this->getIntersect();
$slope = $this->getSlope();
foreach ($slope as $key => $value) {
if ($value != 0.0) {
$retVal += $value * pow($xValue, $key + 1);
}
}
return $retVal;
}
/**
* Return the X-Value for a specified value of Y
*
* @param float $yValue Y-Value
* @return float X-Value
**/
public function getValueOfXForY($yValue)
{
return ($yValue - $this->getIntersect()) / $this->getSlope();
}
/**
* Return the Equation of the best-fit line
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getEquation($dp = 0)
{
$slope = $this->getSlope($dp);
$intersect = $this->getIntersect($dp);
$equation = 'Y = ' . $intersect;
foreach ($slope as $key => $value) {
if ($value != 0.0) {
$equation .= ' + ' . $value . ' * X';
if ($key > 0) {
$equation .= '^' . ($key + 1);
}
}
}
return $equation;
}
/**
* Return the Slope of the line
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getSlope($dp = 0)
{
if ($dp != 0) {
$coefficients = array();
foreach ($this->_slope as $coefficient) {
$coefficients[] = round($coefficient, $dp);
}
return $coefficients;
}
return $this->_slope;
}
public function getCoefficients($dp = 0)
{
return array_merge(array($this->getIntersect($dp)), $this->getSlope($dp));
}
/**
* Execute the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param int $order Order of Polynomial for this regression
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
private function polynomialRegression($order, $yValues, $xValues, $const)
{
// calculate sums
$x_sum = array_sum($xValues);
$y_sum = array_sum($yValues);
$xx_sum = $xy_sum = 0;
for ($i = 0; $i < $this->valueCount; ++$i) {
$xy_sum += $xValues[$i] * $yValues[$i];
$xx_sum += $xValues[$i] * $xValues[$i];
$yy_sum += $yValues[$i] * $yValues[$i];
}
/*
* This routine uses logic from the PHP port of polyfit version 0.1
* written by Michael Bommarito and Paul Meagher
*
* The function fits a polynomial function of order $order through
* a series of x-y data points using least squares.
*
*/
for ($i = 0; $i < $this->valueCount; ++$i) {
for ($j = 0; $j <= $order; ++$j) {
$A[$i][$j] = pow($xValues[$i], $j);
}
}
for ($i=0; $i < $this->valueCount; ++$i) {
$B[$i] = array($yValues[$i]);
}
$matrixA = new Matrix($A);
$matrixB = new Matrix($B);
$C = $matrixA->solve($matrixB);
$coefficients = array();
for ($i = 0; $i < $C->m; ++$i) {
$r = $C->get($i, 0);
if (abs($r) <= pow(10, -9)) {
$r = 0;
}
$coefficients[] = $r;
}
$this->intersect = array_shift($coefficients);
$this->_slope = $coefficients;
$this->calculateGoodnessOfFit($x_sum, $y_sum, $xx_sum, $yy_sum, $xy_sum);
foreach ($this->xValues as $xKey => $xValue) {
$this->yBestFitValues[$xKey] = $this->getValueOfYForX($xValue);
}
}
/**
* Define the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param int $order Order of Polynomial for this regression
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
public function __construct($order, $yValues, $xValues = array(), $const = true)
{
if (parent::__construct($yValues, $xValues) !== false) {
if ($order < $this->valueCount) {
$this->bestFitType .= '_'.$order;
$this->order = $order;
$this->polynomialRegression($order, $yValues, $xValues, $const);
if (($this->getGoodnessOfFit() < 0.0) || ($this->getGoodnessOfFit() > 1.0)) {
$this->_error = true;
}
} else {
$this->_error = true;
}
}
}
}

138
extend/PHPExcel/PHPExcel/Shared/trend/powerBestFitClass.php

@ -0,0 +1,138 @@
<?php
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php';
/**
* PHPExcel_Power_Best_Fit
*
* Copyright (c) 2006 - 2015 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_Shared_Trend
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit
{
/**
* Algorithm type to use for best-fit
* (Name of this trend class)
*
* @var string
**/
protected $bestFitType = 'power';
/**
* Return the Y-Value for a specified value of X
*
* @param float $xValue X-Value
* @return float Y-Value
**/
public function getValueOfYForX($xValue)
{
return $this->getIntersect() * pow(($xValue - $this->xOffset), $this->getSlope());
}
/**
* Return the X-Value for a specified value of Y
*
* @param float $yValue Y-Value
* @return float X-Value
**/
public function getValueOfXForY($yValue)
{
return pow((($yValue + $this->yOffset) / $this->getIntersect()), (1 / $this->getSlope()));
}
/**
* Return the Equation of the best-fit line
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getEquation($dp = 0)
{
$slope = $this->getSlope($dp);
$intersect = $this->getIntersect($dp);
return 'Y = ' . $intersect . ' * X^' . $slope;
}
/**
* Return the Value of X where it intersects Y = 0
*
* @param int $dp Number of places of decimal precision to display
* @return string
**/
public function getIntersect($dp = 0)
{
if ($dp != 0) {
return round(exp($this->intersect), $dp);
}
return exp($this->intersect);
}
/**
* Execute the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
private function powerRegression($yValues, $xValues, $const)
{
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);
}
/**
* Define the regression and calculate the goodness of fit for a set of X and Y data values
*
* @param float[] $yValues The set of Y-values for this regression
* @param float[] $xValues The set of X-values for this regression
* @param boolean $const
*/
public function __construct($yValues, $xValues = array(), $const = true)
{
if (parent::__construct($yValues, $xValues) !== false) {
$this->powerRegression($yValues, $xValues, $const);
}
}
}

147
extend/PHPExcel/PHPExcel/Shared/trend/trendClass.php

@ -0,0 +1,147 @@
<?php
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/linearBestFitClass.php';
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/logarithmicBestFitClass.php';
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/exponentialBestFitClass.php';
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/powerBestFitClass.php';
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/polynomialBestFitClass.php';
/**
* PHPExcel_trendClass
*
* Copyright (c) 2006 - 2015 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_Shared_Trend
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class trendClass
{
const TREND_LINEAR = 'Linear';
const TREND_LOGARITHMIC = 'Logarithmic';
const TREND_EXPONENTIAL = 'Exponential';
const TREND_POWER = 'Power';
const TREND_POLYNOMIAL_2 = 'Polynomial_2';
const TREND_POLYNOMIAL_3 = 'Polynomial_3';
const TREND_POLYNOMIAL_4 = 'Polynomial_4';
const TREND_POLYNOMIAL_5 = 'Polynomial_5';
const TREND_POLYNOMIAL_6 = 'Polynomial_6';
const TREND_BEST_FIT = 'Bestfit';
const TREND_BEST_FIT_NO_POLY = 'Bestfit_no_Polynomials';
/**
* Names of the best-fit trend analysis methods
*
* @var string[]
**/
private static $trendTypes = array(
self::TREND_LINEAR,
self::TREND_LOGARITHMIC,
self::TREND_EXPONENTIAL,
self::TREND_POWER
);
/**
* Names of the best-fit trend polynomial orders
*
* @var string[]
**/
private static $trendTypePolynomialOrders = array(
self::TREND_POLYNOMIAL_2,
self::TREND_POLYNOMIAL_3,
self::TREND_POLYNOMIAL_4,
self::TREND_POLYNOMIAL_5,
self::TREND_POLYNOMIAL_6
);
/**
* Cached results for each method when trying to identify which provides the best fit
*
* @var PHPExcel_Best_Fit[]
**/
private static $trendCache = array();
public static function calculate($trendType = self::TREND_BEST_FIT, $yValues, $xValues = array(), $const = true)
{
// Calculate number of points in each dataset
$nY = count($yValues);
$nX = count($xValues);
// Define X Values if necessary
if ($nX == 0) {
$xValues = range(1, $nY);
$nX = $nY;
} elseif ($nY != $nX) {
// Ensure both arrays of points are the same size
trigger_error("trend(): Number of elements in coordinate arrays do not match.", E_USER_ERROR);
}
$key = md5($trendType.$const.serialize($yValues).serialize($xValues));
// Determine which trend method has been requested
switch ($trendType) {
// Instantiate and return the class for the requested trend method
case self::TREND_LINEAR:
case self::TREND_LOGARITHMIC:
case self::TREND_EXPONENTIAL:
case self::TREND_POWER:
if (!isset(self::$trendCache[$key])) {
$className = 'PHPExcel_'.$trendType.'_Best_Fit';
self::$trendCache[$key] = new $className($yValues, $xValues, $const);
}
return self::$trendCache[$key];
case self::TREND_POLYNOMIAL_2:
case self::TREND_POLYNOMIAL_3:
case self::TREND_POLYNOMIAL_4:
case self::TREND_POLYNOMIAL_5:
case self::TREND_POLYNOMIAL_6:
if (!isset(self::$trendCache[$key])) {
$order = substr($trendType, -1);
self::$trendCache[$key] = new PHPExcel_Polynomial_Best_Fit($order, $yValues, $xValues, $const);
}
return self::$trendCache[$key];
case self::TREND_BEST_FIT:
case self::TREND_BEST_FIT_NO_POLY:
// If the request is to determine the best fit regression, then we test each trend line in turn
// Start by generating an instance of each available trend method
foreach (self::$trendTypes as $trendMethod) {
$className = 'PHPExcel_'.$trendMethod.'BestFit';
$bestFit[$trendMethod] = new $className($yValues, $xValues, $const);
$bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
}
if ($trendType != self::TREND_BEST_FIT_NO_POLY) {
foreach (self::$trendTypePolynomialOrders as $trendMethod) {
$order = substr($trendMethod, -1);
$bestFit[$trendMethod] = new PHPExcel_Polynomial_Best_Fit($order, $yValues, $xValues, $const);
if ($bestFit[$trendMethod]->getError()) {
unset($bestFit[$trendMethod]);
} else {
$bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
}
}
}
// Determine which of our trend lines is the best fit, and then we return the instance of that trend class
arsort($bestFitValue);
$bestFitType = key($bestFitValue);
return $bestFit[$bestFitType];
default:
return false;
}
}
}

846
extend/PHPExcel/PHPExcel/Worksheet/AutoFilter.php

@ -0,0 +1,846 @@
<?php
/**
* PHPExcel_Worksheet_AutoFilter
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_AutoFilter
{
/**
* Autofilter Worksheet
*
* @var PHPExcel_Worksheet
*/
private $workSheet;
/**
* Autofilter Range
*
* @var string
*/
private $range = '';
/**
* Autofilter Column Ruleset
*
* @var array of PHPExcel_Worksheet_AutoFilter_Column
*/
private $columns = array();
/**
* Create a new PHPExcel_Worksheet_AutoFilter
*
* @param string $pRange Cell range (i.e. A1:E10)
* @param PHPExcel_Worksheet $pSheet
*/
public function __construct($pRange = '', PHPExcel_Worksheet $pSheet = null)
{
$this->range = $pRange;
$this->workSheet = $pSheet;
}
/**
* Get AutoFilter Parent Worksheet
*
* @return PHPExcel_Worksheet
*/
public function getParent()
{
return $this->workSheet;
}
/**
* Set AutoFilter Parent Worksheet
*
* @param PHPExcel_Worksheet $pSheet
* @return PHPExcel_Worksheet_AutoFilter
*/
public function setParent(PHPExcel_Worksheet $pSheet = null)
{
$this->workSheet = $pSheet;
return $this;
}
/**
* Get AutoFilter Range
*
* @return string
*/
public function getRange()
{
return $this->range;
}
/**
* Set AutoFilter Range
*
* @param string $pRange Cell range (i.e. A1:E10)
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter
*/
public function setRange($pRange = '')
{
// Uppercase coordinate
$cellAddress = explode('!', strtoupper($pRange));
if (count($cellAddress) > 1) {
list($worksheet, $pRange) = $cellAddress;
}
if (strpos($pRange, ':') !== false) {
$this->range = $pRange;
} elseif (empty($pRange)) {
$this->range = '';
} else {
throw new PHPExcel_Exception('Autofilter must be set on a range of cells.');
}
if (empty($pRange)) {
// Discard all column rules
$this->columns = array();
} else {
// Discard any column rules that are no longer valid within this range
list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
foreach ($this->columns as $key => $value) {
$colIndex = PHPExcel_Cell::columnIndexFromString($key);
if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) {
unset($this->columns[$key]);
}
}
}
return $this;
}
/**
* Get all AutoFilter Columns
*
* @throws PHPExcel_Exception
* @return array of PHPExcel_Worksheet_AutoFilter_Column
*/
public function getColumns()
{
return $this->columns;
}
/**
* Validate that the specified column is in the AutoFilter range
*
* @param string $column Column name (e.g. A)
* @throws PHPExcel_Exception
* @return integer The column offset within the autofilter range
*/
public function testColumnInRange($column)
{
if (empty($this->range)) {
throw new PHPExcel_Exception("No autofilter range is defined.");
}
$columnIndex = PHPExcel_Cell::columnIndexFromString($column);
list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) {
throw new PHPExcel_Exception("Column is outside of current autofilter range.");
}
return $columnIndex - $rangeStart[0];
}
/**
* Get a specified AutoFilter Column Offset within the defined AutoFilter range
*
* @param string $pColumn Column name (e.g. A)
* @throws PHPExcel_Exception
* @return integer The offset of the specified column within the autofilter range
*/
public function getColumnOffset($pColumn)
{
return $this->testColumnInRange($pColumn);
}
/**
* Get a specified AutoFilter Column
*
* @param string $pColumn Column name (e.g. A)
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function getColumn($pColumn)
{
$this->testColumnInRange($pColumn);
if (!isset($this->columns[$pColumn])) {
$this->columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this);
}
return $this->columns[$pColumn];
}
/**
* Get a specified AutoFilter Column by it's offset
*
* @param integer $pColumnOffset Column offset within range (starting from 0)
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function getColumnByOffset($pColumnOffset = 0)
{
list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
$pColumn = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $pColumnOffset - 1);
return $this->getColumn($pColumn);
}
/**
* Set AutoFilter
*
* @param PHPExcel_Worksheet_AutoFilter_Column|string $pColumn
* A simple string containing a Column ID like 'A' is permitted
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter
*/
public function setColumn($pColumn)
{
if ((is_string($pColumn)) && (!empty($pColumn))) {
$column = $pColumn;
} elseif (is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) {
$column = $pColumn->getColumnIndex();
} else {
throw new PHPExcel_Exception("Column is not within the autofilter range.");
}
$this->testColumnInRange($column);
if (is_string($pColumn)) {
$this->columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this);
} elseif (is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) {
$pColumn->setParent($this);
$this->columns[$column] = $pColumn;
}
ksort($this->columns);
return $this;
}
/**
* Clear a specified AutoFilter Column
*
* @param string $pColumn Column name (e.g. A)
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter
*/
public function clearColumn($pColumn)
{
$this->testColumnInRange($pColumn);
if (isset($this->columns[$pColumn])) {
unset($this->columns[$pColumn]);
}
return $this;
}
/**
* Shift an AutoFilter Column Rule to a different column
*
* Note: This method bypasses validation of the destination column to ensure it is within this AutoFilter range.
* Nor does it verify whether any column rule already exists at $toColumn, but will simply overrideany existing value.
* Use with caution.
*
* @param string $fromColumn Column name (e.g. A)
* @param string $toColumn Column name (e.g. B)
* @return PHPExcel_Worksheet_AutoFilter
*/
public function shiftColumn($fromColumn = null, $toColumn = null)
{
$fromColumn = strtoupper($fromColumn);
$toColumn = strtoupper($toColumn);
if (($fromColumn !== null) && (isset($this->columns[$fromColumn])) && ($toColumn !== null)) {
$this->columns[$fromColumn]->setParent();
$this->columns[$fromColumn]->setColumnIndex($toColumn);
$this->columns[$toColumn] = $this->columns[$fromColumn];
$this->columns[$toColumn]->setParent($this);
unset($this->columns[$fromColumn]);
ksort($this->columns);
}
return $this;
}
/**
* Test if cell value is in the defined set of values
*
* @param mixed $cellValue
* @param mixed[] $dataSet
* @return boolean
*/
private static function filterTestInSimpleDataSet($cellValue, $dataSet)
{
$dataSetValues = $dataSet['filterValues'];
$blanks = $dataSet['blanks'];
if (($cellValue == '') || ($cellValue === null)) {
return $blanks;
}
return in_array($cellValue, $dataSetValues);
}
/**
* Test if cell value is in the defined set of Excel date values
*
* @param mixed $cellValue
* @param mixed[] $dataSet
* @return boolean
*/
private static function filterTestInDateGroupSet($cellValue, $dataSet)
{
$dateSet = $dataSet['filterValues'];
$blanks = $dataSet['blanks'];
if (($cellValue == '') || ($cellValue === null)) {
return $blanks;
}
if (is_numeric($cellValue)) {
$dateValue = PHPExcel_Shared_Date::ExcelToPHP($cellValue);
if ($cellValue < 1) {
// Just the time part
$dtVal = date('His', $dateValue);
$dateSet = $dateSet['time'];
} elseif ($cellValue == floor($cellValue)) {
// Just the date part
$dtVal = date('Ymd', $dateValue);
$dateSet = $dateSet['date'];
} else {
// date and time parts
$dtVal = date('YmdHis', $dateValue);
$dateSet = $dateSet['dateTime'];
}
foreach ($dateSet as $dateValue) {
// Use of substr to extract value at the appropriate group level
if (substr($dtVal, 0, strlen($dateValue)) == $dateValue) {
return true;
}
}
}
return false;
}
/**
* Test if cell value is within a set of values defined by a ruleset
*
* @param mixed $cellValue
* @param mixed[] $ruleSet
* @return boolean
*/
private static function filterTestInCustomDataSet($cellValue, $ruleSet)
{
$dataSet = $ruleSet['filterRules'];
$join = $ruleSet['join'];
$customRuleForBlanks = isset($ruleSet['customRuleForBlanks']) ? $ruleSet['customRuleForBlanks'] : false;
if (!$customRuleForBlanks) {
// Blank cells are always ignored, so return a FALSE
if (($cellValue == '') || ($cellValue === null)) {
return false;
}
}
$returnVal = ($join == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND);
foreach ($dataSet as $rule) {
if (is_numeric($rule['value'])) {
// Numeric values are tested using the appropriate operator
switch ($rule['operator']) {
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
$retVal = ($cellValue == $rule['value']);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
$retVal = ($cellValue != $rule['value']);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN:
$retVal = ($cellValue > $rule['value']);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL:
$retVal = ($cellValue >= $rule['value']);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN:
$retVal = ($cellValue < $rule['value']);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL:
$retVal = ($cellValue <= $rule['value']);
break;
}
} elseif ($rule['value'] == '') {
switch ($rule['operator']) {
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
$retVal = (($cellValue == '') || ($cellValue === null));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
$retVal = (($cellValue != '') && ($cellValue !== null));
break;
default:
$retVal = true;
break;
}
} else {
// String values are always tested for equality, factoring in for wildcards (hence a regexp test)
$retVal = preg_match('/^'.$rule['value'].'$/i', $cellValue);
}
// If there are multiple conditions, then we need to test both using the appropriate join operator
switch ($join) {
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR:
$returnVal = $returnVal || $retVal;
// Break as soon as we have a TRUE match for OR joins,
// to avoid unnecessary additional code execution
if ($returnVal) {
return $returnVal;
}
break;
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND:
$returnVal = $returnVal && $retVal;
break;
}
}
return $returnVal;
}
/**
* Test if cell date value is matches a set of values defined by a set of months
*
* @param mixed $cellValue
* @param mixed[] $monthSet
* @return boolean
*/
private static function filterTestInPeriodDateSet($cellValue, $monthSet)
{
// Blank cells are always ignored, so return a FALSE
if (($cellValue == '') || ($cellValue === null)) {
return false;
}
if (is_numeric($cellValue)) {
$dateValue = date('m', PHPExcel_Shared_Date::ExcelToPHP($cellValue));
if (in_array($dateValue, $monthSet)) {
return true;
}
}
return false;
}
/**
* Search/Replace arrays to convert Excel wildcard syntax to a regexp syntax for preg_matching
*
* @var array
*/
private static $fromReplace = array('\*', '\?', '~~', '~.*', '~.?');
private static $toReplace = array('.*', '.', '~', '\*', '\?');
/**
* Convert a dynamic rule daterange to a custom filter range expression for ease of calculation
*
* @param string $dynamicRuleType
* @param PHPExcel_Worksheet_AutoFilter_Column &$filterColumn
* @return mixed[]
*/
private function dynamicFilterDateRange($dynamicRuleType, &$filterColumn)
{
$rDateType = PHPExcel_Calculation_Functions::getReturnDateType();
PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC);
$val = $maxVal = null;
$ruleValues = array();
$baseDate = PHPExcel_Calculation_DateTime::DATENOW();
// Calculate start/end dates for the required date range based on current date
switch ($dynamicRuleType) {
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK:
$baseDate = strtotime('-7 days', $baseDate);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK:
$baseDate = strtotime('-7 days', $baseDate);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH:
$baseDate = strtotime('-1 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH:
$baseDate = strtotime('+1 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER:
$baseDate = strtotime('-3 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER:
$baseDate = strtotime('+3 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR:
$baseDate = strtotime('-1 year', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR:
$baseDate = strtotime('+1 year', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
break;
}
switch ($dynamicRuleType) {
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW:
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day', $baseDate));
$val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate);
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE:
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day', $baseDate));
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1, date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR:
$maxVal = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 31, 12, date('Y', $baseDate)));
++$maxVal;
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1, date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER:
$thisMonth = date('m', $baseDate);
$thisQuarter = floor(--$thisMonth / 3);
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0, 0, 0, date('t', $baseDate), (1+$thisQuarter)*3, date('Y', $baseDate)));
++$maxVal;
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1+$thisQuarter*3, date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH:
$maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0, 0, 0, date('t', $baseDate), date('m', $baseDate), date('Y', $baseDate)));
++$maxVal;
$val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK:
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK:
$dayOfWeek = date('w', $baseDate);
$val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate) - $dayOfWeek;
$maxVal = $val + 7;
break;
}
switch ($dynamicRuleType) {
// Adjust Today dates for Yesterday and Tomorrow
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY:
--$maxVal;
--$val;
break;
case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW:
++$maxVal;
++$val;
break;
}
// Set the filter column rule attributes ready for writing
$filterColumn->setAttributes(array('val' => $val, 'maxVal' => $maxVal));
// Set the rules for identifying rows for hide/show
$ruleValues[] = array('operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, 'value' => $val);
$ruleValues[] = array('operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN, 'value' => $maxVal);
PHPExcel_Calculation_Functions::setReturnDateType($rDateType);
return array('method' => 'filterTestInCustomDataSet', 'arguments' => array('filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND));
}
private function calculateTopTenValue($columnID, $startRow, $endRow, $ruleType, $ruleValue)
{
$range = $columnID.$startRow.':'.$columnID.$endRow;
$dataValues = PHPExcel_Calculation_Functions::flattenArray($this->workSheet->rangeToArray($range, null, true, false));
$dataValues = array_filter($dataValues);
if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) {
rsort($dataValues);
} else {
sort($dataValues);
}
return array_pop(array_slice($dataValues, 0, $ruleValue));
}
/**
* Apply the AutoFilter rules to the AutoFilter Range
*
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter
*/
public function showHideRows()
{
list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->range);
// The heading row should always be visible
// echo 'AutoFilter Heading Row ', $rangeStart[1],' is always SHOWN',PHP_EOL;
$this->workSheet->getRowDimension($rangeStart[1])->setVisible(true);
$columnFilterTests = array();
foreach ($this->columns as $columnID => $filterColumn) {
$rules = $filterColumn->getRules();
switch ($filterColumn->getFilterType()) {
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER:
$ruleValues = array();
// Build a list of the filter value selections
foreach ($rules as $rule) {
$ruleType = $rule->getRuleType();
$ruleValues[] = $rule->getValue();
}
// Test if we want to include blanks in our filter criteria
$blanks = false;
$ruleDataSet = array_filter($ruleValues);
if (count($ruleValues) != count($ruleDataSet)) {
$blanks = true;
}
if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER) {
// Filter on absolute values
$columnFilterTests[$columnID] = array(
'method' => 'filterTestInSimpleDataSet',
'arguments' => array('filterValues' => $ruleDataSet, 'blanks' => $blanks)
);
} else {
// Filter on date group values
$arguments = array(
'date' => array(),
'time' => array(),
'dateTime' => array(),
);
foreach ($ruleDataSet as $ruleValue) {
$date = $time = '';
if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR])) &&
($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR] !== '')) {
$date .= sprintf('%04d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR]);
}
if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH])) &&
($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH] != '')) {
$date .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH]);
}
if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY])) &&
($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY] !== '')) {
$date .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY]);
}
if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR])) &&
($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR] !== '')) {
$time .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR]);
}
if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE])) &&
($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE] !== '')) {
$time .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE]);
}
if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND])) &&
($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND] !== '')) {
$time .= sprintf('%02d', $ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND]);
}
$dateTime = $date . $time;
$arguments['date'][] = $date;
$arguments['time'][] = $time;
$arguments['dateTime'][] = $dateTime;
}
// Remove empty elements
$arguments['date'] = array_filter($arguments['date']);
$arguments['time'] = array_filter($arguments['time']);
$arguments['dateTime'] = array_filter($arguments['dateTime']);
$columnFilterTests[$columnID] = array(
'method' => 'filterTestInDateGroupSet',
'arguments' => array('filterValues' => $arguments, 'blanks' => $blanks)
);
}
break;
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER:
$customRuleForBlanks = false;
$ruleValues = array();
// Build a list of the filter value selections
foreach ($rules as $rule) {
$ruleType = $rule->getRuleType();
$ruleValue = $rule->getValue();
if (!is_numeric($ruleValue)) {
// Convert to a regexp allowing for regexp reserved characters, wildcards and escaped wildcards
$ruleValue = preg_quote($ruleValue);
$ruleValue = str_replace(self::$fromReplace, self::$toReplace, $ruleValue);
if (trim($ruleValue) == '') {
$customRuleForBlanks = true;
$ruleValue = trim($ruleValue);
}
}
$ruleValues[] = array('operator' => $rule->getOperator(), 'value' => $ruleValue);
}
$join = $filterColumn->getJoin();
$columnFilterTests[$columnID] = array(
'method' => 'filterTestInCustomDataSet',
'arguments' => array('filterRules' => $ruleValues, 'join' => $join, 'customRuleForBlanks' => $customRuleForBlanks)
);
break;
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER:
$ruleValues = array();
foreach ($rules as $rule) {
// We should only ever have one Dynamic Filter Rule anyway
$dynamicRuleType = $rule->getGrouping();
if (($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) ||
($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE)) {
// Number (Average) based
// Calculate the average
$averageFormula = '=AVERAGE('.$columnID.($rangeStart[1]+1).':'.$columnID.$rangeEnd[1].')';
$average = PHPExcel_Calculation::getInstance()->calculateFormula($averageFormula, null, $this->workSheet->getCell('A1'));
// Set above/below rule based on greaterThan or LessTan
$operator = ($dynamicRuleType === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE)
? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN
: PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN;
$ruleValues[] = array('operator' => $operator,
'value' => $average
);
$columnFilterTests[$columnID] = array(
'method' => 'filterTestInCustomDataSet',
'arguments' => array('filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR)
);
} else {
// Date based
if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') {
// Month or Quarter
sscanf($dynamicRuleType, '%[A-Z]%d', $periodType, $period);
if ($periodType == 'M') {
$ruleValues = array($period);
} else {
--$period;
$periodEnd = (1+$period)*3;
$periodStart = 1+$period*3;
$ruleValues = range($periodStart, $periodEnd);
}
$columnFilterTests[$columnID] = array(
'method' => 'filterTestInPeriodDateSet',
'arguments' => $ruleValues
);
$filterColumn->setAttributes(array());
} else {
// Date Range
$columnFilterTests[$columnID] = $this->dynamicFilterDateRange($dynamicRuleType, $filterColumn);
break;
}
}
}
break;
case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER:
$ruleValues = array();
$dataRowCount = $rangeEnd[1] - $rangeStart[1];
foreach ($rules as $rule) {
// We should only ever have one Dynamic Filter Rule anyway
$toptenRuleType = $rule->getGrouping();
$ruleValue = $rule->getValue();
$ruleOperator = $rule->getOperator();
}
if ($ruleOperator === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) {
$ruleValue = floor($ruleValue * ($dataRowCount / 100));
}
if ($ruleValue < 1) {
$ruleValue = 1;
}
if ($ruleValue > 500) {
$ruleValue = 500;
}
$maxVal = $this->calculateTopTenValue($columnID, $rangeStart[1]+1, $rangeEnd[1], $toptenRuleType, $ruleValue);
$operator = ($toptenRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP)
? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL
: PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL;
$ruleValues[] = array('operator' => $operator, 'value' => $maxVal);
$columnFilterTests[$columnID] = array(
'method' => 'filterTestInCustomDataSet',
'arguments' => array('filterRules' => $ruleValues, 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR)
);
$filterColumn->setAttributes(array('maxVal' => $maxVal));
break;
}
}
// echo 'Column Filter Test CRITERIA',PHP_EOL;
// var_dump($columnFilterTests);
//
// Execute the column tests for each row in the autoFilter range to determine show/hide,
for ($row = $rangeStart[1]+1; $row <= $rangeEnd[1]; ++$row) {
// echo 'Testing Row = ', $row,PHP_EOL;
$result = true;
foreach ($columnFilterTests as $columnID => $columnFilterTest) {
// echo 'Testing cell ', $columnID.$row,PHP_EOL;
$cellValue = $this->workSheet->getCell($columnID.$row)->getCalculatedValue();
// echo 'Value is ', $cellValue,PHP_EOL;
// Execute the filter test
$result = $result &&
call_user_func_array(
array('PHPExcel_Worksheet_AutoFilter', $columnFilterTest['method']),
array($cellValue, $columnFilterTest['arguments'])
);
// echo (($result) ? 'VALID' : 'INVALID'),PHP_EOL;
// If filter test has resulted in FALSE, exit the loop straightaway rather than running any more tests
if (!$result) {
break;
}
}
// Set show/hide for the row based on the result of the autoFilter result
// echo (($result) ? 'SHOW' : 'HIDE'),PHP_EOL;
$this->workSheet->getRowDimension($row)->setVisible($result);
}
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
if ($key == 'workSheet') {
// Detach from worksheet
$this->{$key} = null;
} else {
$this->{$key} = clone $value;
}
} elseif ((is_array($value)) && ($key == 'columns')) {
// The columns array of PHPExcel_Worksheet_AutoFilter objects
$this->{$key} = array();
foreach ($value as $k => $v) {
$this->{$key}[$k] = clone $v;
// attach the new cloned Column to this new cloned Autofilter object
$this->{$key}[$k]->setParent($this);
}
} else {
$this->{$key} = $value;
}
}
}
/**
* toString method replicates previous behavior by returning the range if object is
* referenced as a property of its parent.
*/
public function __toString()
{
return (string) $this->range;
}
}

405
extend/PHPExcel/PHPExcel/Worksheet/AutoFilter/Column.php

@ -0,0 +1,405 @@
<?php
/**
* PHPExcel_Worksheet_AutoFilter_Column
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_AutoFilter_Column
{
const AUTOFILTER_FILTERTYPE_FILTER = 'filters';
const AUTOFILTER_FILTERTYPE_CUSTOMFILTER = 'customFilters';
// Supports no more than 2 rules, with an And/Or join criteria
// if more than 1 rule is defined
const AUTOFILTER_FILTERTYPE_DYNAMICFILTER = 'dynamicFilter';
// Even though the filter rule is constant, the filtered data can vary
// e.g. filtered by date = TODAY
const AUTOFILTER_FILTERTYPE_TOPTENFILTER = 'top10';
/**
* Types of autofilter rules
*
* @var string[]
*/
private static $filterTypes = array(
// Currently we're not handling
// colorFilter
// extLst
// iconFilter
self::AUTOFILTER_FILTERTYPE_FILTER,
self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER,
self::AUTOFILTER_FILTERTYPE_DYNAMICFILTER,
self::AUTOFILTER_FILTERTYPE_TOPTENFILTER,
);
/* Multiple Rule Connections */
const AUTOFILTER_COLUMN_JOIN_AND = 'and';
const AUTOFILTER_COLUMN_JOIN_OR = 'or';
/**
* Join options for autofilter rules
*
* @var string[]
*/
private static $ruleJoins = array(
self::AUTOFILTER_COLUMN_JOIN_AND,
self::AUTOFILTER_COLUMN_JOIN_OR,
);
/**
* Autofilter
*
* @var PHPExcel_Worksheet_AutoFilter
*/
private $parent;
/**
* Autofilter Column Index
*
* @var string
*/
private $columnIndex = '';
/**
* Autofilter Column Filter Type
*
* @var string
*/
private $filterType = self::AUTOFILTER_FILTERTYPE_FILTER;
/**
* Autofilter Multiple Rules And/Or
*
* @var string
*/
private $join = self::AUTOFILTER_COLUMN_JOIN_OR;
/**
* Autofilter Column Rules
*
* @var array of PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
private $ruleset = array();
/**
* Autofilter Column Dynamic Attributes
*
* @var array of mixed
*/
private $attributes = array();
/**
* Create a new PHPExcel_Worksheet_AutoFilter_Column
*
* @param string $pColumn Column (e.g. A)
* @param PHPExcel_Worksheet_AutoFilter $pParent Autofilter for this column
*/
public function __construct($pColumn, PHPExcel_Worksheet_AutoFilter $pParent = null)
{
$this->columnIndex = $pColumn;
$this->parent = $pParent;
}
/**
* Get AutoFilter Column Index
*
* @return string
*/
public function getColumnIndex()
{
return $this->columnIndex;
}
/**
* Set AutoFilter Column Index
*
* @param string $pColumn Column (e.g. A)
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setColumnIndex($pColumn)
{
// Uppercase coordinate
$pColumn = strtoupper($pColumn);
if ($this->parent !== null) {
$this->parent->testColumnInRange($pColumn);
}
$this->columnIndex = $pColumn;
return $this;
}
/**
* Get this Column's AutoFilter Parent
*
* @return PHPExcel_Worksheet_AutoFilter
*/
public function getParent()
{
return $this->parent;
}
/**
* Set this Column's AutoFilter Parent
*
* @param PHPExcel_Worksheet_AutoFilter
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setParent(PHPExcel_Worksheet_AutoFilter $pParent = null)
{
$this->parent = $pParent;
return $this;
}
/**
* Get AutoFilter Type
*
* @return string
*/
public function getFilterType()
{
return $this->filterType;
}
/**
* Set AutoFilter Type
*
* @param string $pFilterType
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setFilterType($pFilterType = self::AUTOFILTER_FILTERTYPE_FILTER)
{
if (!in_array($pFilterType, self::$filterTypes)) {
throw new PHPExcel_Exception('Invalid filter type for column AutoFilter.');
}
$this->filterType = $pFilterType;
return $this;
}
/**
* Get AutoFilter Multiple Rules And/Or Join
*
* @return string
*/
public function getJoin()
{
return $this->join;
}
/**
* Set AutoFilter Multiple Rules And/Or
*
* @param string $pJoin And/Or
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setJoin($pJoin = self::AUTOFILTER_COLUMN_JOIN_OR)
{
// Lowercase And/Or
$pJoin = strtolower($pJoin);
if (!in_array($pJoin, self::$ruleJoins)) {
throw new PHPExcel_Exception('Invalid rule connection for column AutoFilter.');
}
$this->join = $pJoin;
return $this;
}
/**
* Set AutoFilter Attributes
*
* @param string[] $pAttributes
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setAttributes($pAttributes = array())
{
$this->attributes = $pAttributes;
return $this;
}
/**
* Set An AutoFilter Attribute
*
* @param string $pName Attribute Name
* @param string $pValue Attribute Value
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setAttribute($pName, $pValue)
{
$this->attributes[$pName] = $pValue;
return $this;
}
/**
* Get AutoFilter Column Attributes
*
* @return string
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* Get specific AutoFilter Column Attribute
*
* @param string $pName Attribute Name
* @return string
*/
public function getAttribute($pName)
{
if (isset($this->attributes[$pName])) {
return $this->attributes[$pName];
}
return null;
}
/**
* Get all AutoFilter Column Rules
*
* @throws PHPExcel_Exception
* @return array of PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function getRules()
{
return $this->ruleset;
}
/**
* Get a specified AutoFilter Column Rule
*
* @param integer $pIndex Rule index in the ruleset array
* @return PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function getRule($pIndex)
{
if (!isset($this->ruleset[$pIndex])) {
$this->ruleset[$pIndex] = new PHPExcel_Worksheet_AutoFilter_Column_Rule($this);
}
return $this->ruleset[$pIndex];
}
/**
* Create a new AutoFilter Column Rule in the ruleset
*
* @return PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function createRule()
{
$this->ruleset[] = new PHPExcel_Worksheet_AutoFilter_Column_Rule($this);
return end($this->ruleset);
}
/**
* Add a new AutoFilter Column Rule to the ruleset
*
* @param PHPExcel_Worksheet_AutoFilter_Column_Rule $pRule
* @param boolean $returnRule Flag indicating whether the rule object or the column object should be returned
* @return PHPExcel_Worksheet_AutoFilter_Column|PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function addRule(PHPExcel_Worksheet_AutoFilter_Column_Rule $pRule, $returnRule = true)
{
$pRule->setParent($this);
$this->ruleset[] = $pRule;
return ($returnRule) ? $pRule : $this;
}
/**
* Delete a specified AutoFilter Column Rule
* If the number of rules is reduced to 1, then we reset And/Or logic to Or
*
* @param integer $pIndex Rule index in the ruleset array
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function deleteRule($pIndex)
{
if (isset($this->ruleset[$pIndex])) {
unset($this->ruleset[$pIndex]);
// If we've just deleted down to a single rule, then reset And/Or joining to Or
if (count($this->ruleset) <= 1) {
$this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
}
}
return $this;
}
/**
* Delete all AutoFilter Column Rules
*
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function clearRules()
{
$this->ruleset = array();
$this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
if ($key == 'parent') {
// Detach from autofilter parent
$this->$key = null;
} else {
$this->$key = clone $value;
}
} elseif ((is_array($value)) && ($key == 'ruleset')) {
// The columns array of PHPExcel_Worksheet_AutoFilter objects
$this->$key = array();
foreach ($value as $k => $v) {
$this->$key[$k] = clone $v;
// attach the new cloned Rule to this new cloned Autofilter Cloned object
$this->$key[$k]->setParent($this);
}
} else {
$this->$key = $value;
}
}
}
}

468
extend/PHPExcel/PHPExcel/Worksheet/AutoFilter/Column/Rule.php

@ -0,0 +1,468 @@
<?php
/**
* PHPExcel_Worksheet_AutoFilter_Column_Rule
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_AutoFilter_Column_Rule
{
const AUTOFILTER_RULETYPE_FILTER = 'filter';
const AUTOFILTER_RULETYPE_DATEGROUP = 'dateGroupItem';
const AUTOFILTER_RULETYPE_CUSTOMFILTER = 'customFilter';
const AUTOFILTER_RULETYPE_DYNAMICFILTER = 'dynamicFilter';
const AUTOFILTER_RULETYPE_TOPTENFILTER = 'top10Filter';
private static $ruleTypes = array(
// Currently we're not handling
// colorFilter
// extLst
// iconFilter
self::AUTOFILTER_RULETYPE_FILTER,
self::AUTOFILTER_RULETYPE_DATEGROUP,
self::AUTOFILTER_RULETYPE_CUSTOMFILTER,
self::AUTOFILTER_RULETYPE_DYNAMICFILTER,
self::AUTOFILTER_RULETYPE_TOPTENFILTER,
);
const AUTOFILTER_RULETYPE_DATEGROUP_YEAR = 'year';
const AUTOFILTER_RULETYPE_DATEGROUP_MONTH = 'month';
const AUTOFILTER_RULETYPE_DATEGROUP_DAY = 'day';
const AUTOFILTER_RULETYPE_DATEGROUP_HOUR = 'hour';
const AUTOFILTER_RULETYPE_DATEGROUP_MINUTE = 'minute';
const AUTOFILTER_RULETYPE_DATEGROUP_SECOND = 'second';
private static $dateTimeGroups = array(
self::AUTOFILTER_RULETYPE_DATEGROUP_YEAR,
self::AUTOFILTER_RULETYPE_DATEGROUP_MONTH,
self::AUTOFILTER_RULETYPE_DATEGROUP_DAY,
self::AUTOFILTER_RULETYPE_DATEGROUP_HOUR,
self::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE,
self::AUTOFILTER_RULETYPE_DATEGROUP_SECOND,
);
const AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY = 'yesterday';
const AUTOFILTER_RULETYPE_DYNAMIC_TODAY = 'today';
const AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW = 'tomorrow';
const AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE = 'yearToDate';
const AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR = 'thisYear';
const AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER = 'thisQuarter';
const AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH = 'thisMonth';
const AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK = 'thisWeek';
const AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR = 'lastYear';
const AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER = 'lastQuarter';
const AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH = 'lastMonth';
const AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK = 'lastWeek';
const AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR = 'nextYear';
const AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER = 'nextQuarter';
const AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH = 'nextMonth';
const AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK = 'nextWeek';
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1 = 'M1';
const AUTOFILTER_RULETYPE_DYNAMIC_JANUARY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2 = 'M2';
const AUTOFILTER_RULETYPE_DYNAMIC_FEBRUARY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3 = 'M3';
const AUTOFILTER_RULETYPE_DYNAMIC_MARCH = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4 = 'M4';
const AUTOFILTER_RULETYPE_DYNAMIC_APRIL = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5 = 'M5';
const AUTOFILTER_RULETYPE_DYNAMIC_MAY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6 = 'M6';
const AUTOFILTER_RULETYPE_DYNAMIC_JUNE = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7 = 'M7';
const AUTOFILTER_RULETYPE_DYNAMIC_JULY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8 = 'M8';
const AUTOFILTER_RULETYPE_DYNAMIC_AUGUST = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9 = 'M9';
const AUTOFILTER_RULETYPE_DYNAMIC_SEPTEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10 = 'M10';
const AUTOFILTER_RULETYPE_DYNAMIC_OCTOBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11 = 'M11';
const AUTOFILTER_RULETYPE_DYNAMIC_NOVEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11;
const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12 = 'M12';
const AUTOFILTER_RULETYPE_DYNAMIC_DECEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12;
const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_1 = 'Q1';
const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_2 = 'Q2';
const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3 = 'Q3';
const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_4 = 'Q4';
const AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE = 'aboveAverage';
const AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE = 'belowAverage';
private static $dynamicTypes = array(
self::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY,
self::AUTOFILTER_RULETYPE_DYNAMIC_TODAY,
self::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW,
self::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE,
self::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR,
self::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER,
self::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH,
self::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK,
self::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR,
self::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER,
self::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH,
self::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK,
self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR,
self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER,
self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH,
self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11,
self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12,
self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_1,
self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_2,
self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3,
self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_4,
self::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE,
self::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE,
);
/*
* The only valid filter rule operators for filter and customFilter types are:
* <xsd:enumeration value="equal"/>
* <xsd:enumeration value="lessThan"/>
* <xsd:enumeration value="lessThanOrEqual"/>
* <xsd:enumeration value="notEqual"/>
* <xsd:enumeration value="greaterThanOrEqual"/>
* <xsd:enumeration value="greaterThan"/>
*/
const AUTOFILTER_COLUMN_RULE_EQUAL = 'equal';
const AUTOFILTER_COLUMN_RULE_NOTEQUAL = 'notEqual';
const AUTOFILTER_COLUMN_RULE_GREATERTHAN = 'greaterThan';
const AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL = 'greaterThanOrEqual';
const AUTOFILTER_COLUMN_RULE_LESSTHAN = 'lessThan';
const AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL = 'lessThanOrEqual';
private static $operators = array(
self::AUTOFILTER_COLUMN_RULE_EQUAL,
self::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
self::AUTOFILTER_COLUMN_RULE_GREATERTHAN,
self::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL,
self::AUTOFILTER_COLUMN_RULE_LESSTHAN,
self::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL,
);
const AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE = 'byValue';
const AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT = 'byPercent';
private static $topTenValue = array(
self::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE,
self::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT,
);
const AUTOFILTER_COLUMN_RULE_TOPTEN_TOP = 'top';
const AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM = 'bottom';
private static $topTenType = array(
self::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP,
self::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM,
);
/* Rule Operators (Numeric, Boolean etc) */
// const AUTOFILTER_COLUMN_RULE_BETWEEN = 'between'; // greaterThanOrEqual 1 && lessThanOrEqual 2
/* Rule Operators (Numeric Special) which are translated to standard numeric operators with calculated values */
// const AUTOFILTER_COLUMN_RULE_TOPTEN = 'topTen'; // greaterThan calculated value
// const AUTOFILTER_COLUMN_RULE_TOPTENPERCENT = 'topTenPercent'; // greaterThan calculated value
// const AUTOFILTER_COLUMN_RULE_ABOVEAVERAGE = 'aboveAverage'; // Value is calculated as the average
// const AUTOFILTER_COLUMN_RULE_BELOWAVERAGE = 'belowAverage'; // Value is calculated as the average
/* Rule Operators (String) which are set as wild-carded values */
// const AUTOFILTER_COLUMN_RULE_BEGINSWITH = 'beginsWith'; // A*
// const AUTOFILTER_COLUMN_RULE_ENDSWITH = 'endsWith'; // *Z
// const AUTOFILTER_COLUMN_RULE_CONTAINS = 'contains'; // *B*
// const AUTOFILTER_COLUMN_RULE_DOESNTCONTAIN = 'notEqual'; // notEqual *B*
/* Rule Operators (Date Special) which are translated to standard numeric operators with calculated values */
// const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan';
// const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan';
// const AUTOFILTER_COLUMN_RULE_YESTERDAY = 'yesterday';
// const AUTOFILTER_COLUMN_RULE_TODAY = 'today';
// const AUTOFILTER_COLUMN_RULE_TOMORROW = 'tomorrow';
// const AUTOFILTER_COLUMN_RULE_LASTWEEK = 'lastWeek';
// const AUTOFILTER_COLUMN_RULE_THISWEEK = 'thisWeek';
// const AUTOFILTER_COLUMN_RULE_NEXTWEEK = 'nextWeek';
// const AUTOFILTER_COLUMN_RULE_LASTMONTH = 'lastMonth';
// const AUTOFILTER_COLUMN_RULE_THISMONTH = 'thisMonth';
// const AUTOFILTER_COLUMN_RULE_NEXTMONTH = 'nextMonth';
// const AUTOFILTER_COLUMN_RULE_LASTQUARTER = 'lastQuarter';
// const AUTOFILTER_COLUMN_RULE_THISQUARTER = 'thisQuarter';
// const AUTOFILTER_COLUMN_RULE_NEXTQUARTER = 'nextQuarter';
// const AUTOFILTER_COLUMN_RULE_LASTYEAR = 'lastYear';
// const AUTOFILTER_COLUMN_RULE_THISYEAR = 'thisYear';
// const AUTOFILTER_COLUMN_RULE_NEXTYEAR = 'nextYear';
// const AUTOFILTER_COLUMN_RULE_YEARTODATE = 'yearToDate'; // <dynamicFilter val="40909" type="yearToDate" maxVal="41113"/>
// const AUTOFILTER_COLUMN_RULE_ALLDATESINMONTH = 'allDatesInMonth'; // <dynamicFilter type="M2"/> for Month/February
// const AUTOFILTER_COLUMN_RULE_ALLDATESINQUARTER = 'allDatesInQuarter'; // <dynamicFilter type="Q2"/> for Quarter 2
/**
* Autofilter Column
*
* @var PHPExcel_Worksheet_AutoFilter_Column
*/
private $parent = null;
/**
* Autofilter Rule Type
*
* @var string
*/
private $ruleType = self::AUTOFILTER_RULETYPE_FILTER;
/**
* Autofilter Rule Value
*
* @var string
*/
private $value = '';
/**
* Autofilter Rule Operator
*
* @var string
*/
private $operator = self::AUTOFILTER_COLUMN_RULE_EQUAL;
/**
* DateTimeGrouping Group Value
*
* @var string
*/
private $grouping = '';
/**
* Create a new PHPExcel_Worksheet_AutoFilter_Column_Rule
*
* @param PHPExcel_Worksheet_AutoFilter_Column $pParent
*/
public function __construct(PHPExcel_Worksheet_AutoFilter_Column $pParent = null)
{
$this->parent = $pParent;
}
/**
* Get AutoFilter Rule Type
*
* @return string
*/
public function getRuleType()
{
return $this->ruleType;
}
/**
* Set AutoFilter Rule Type
*
* @param string $pRuleType
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function setRuleType($pRuleType = self::AUTOFILTER_RULETYPE_FILTER)
{
if (!in_array($pRuleType, self::$ruleTypes)) {
throw new PHPExcel_Exception('Invalid rule type for column AutoFilter Rule.');
}
$this->ruleType = $pRuleType;
return $this;
}
/**
* Get AutoFilter Rule Value
*
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* Set AutoFilter Rule Value
*
* @param string|string[] $pValue
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function setValue($pValue = '')
{
if (is_array($pValue)) {
$grouping = -1;
foreach ($pValue as $key => $value) {
// Validate array entries
if (!in_array($key, self::$dateTimeGroups)) {
// Remove any invalid entries from the value array
unset($pValue[$key]);
} else {
// Work out what the dateTime grouping will be
$grouping = max($grouping, array_search($key, self::$dateTimeGroups));
}
}
if (count($pValue) == 0) {
throw new PHPExcel_Exception('Invalid rule value for column AutoFilter Rule.');
}
// Set the dateTime grouping that we've anticipated
$this->setGrouping(self::$dateTimeGroups[$grouping]);
}
$this->value = $pValue;
return $this;
}
/**
* Get AutoFilter Rule Operator
*
* @return string
*/
public function getOperator()
{
return $this->operator;
}
/**
* Set AutoFilter Rule Operator
*
* @param string $pOperator
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function setOperator($pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL)
{
if (empty($pOperator)) {
$pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL;
}
if ((!in_array($pOperator, self::$operators)) &&
(!in_array($pOperator, self::$topTenValue))) {
throw new PHPExcel_Exception('Invalid operator for column AutoFilter Rule.');
}
$this->operator = $pOperator;
return $this;
}
/**
* Get AutoFilter Rule Grouping
*
* @return string
*/
public function getGrouping()
{
return $this->grouping;
}
/**
* Set AutoFilter Rule Grouping
*
* @param string $pGrouping
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function setGrouping($pGrouping = null)
{
if (($pGrouping !== null) &&
(!in_array($pGrouping, self::$dateTimeGroups)) &&
(!in_array($pGrouping, self::$dynamicTypes)) &&
(!in_array($pGrouping, self::$topTenType))) {
throw new PHPExcel_Exception('Invalid rule type for column AutoFilter Rule.');
}
$this->grouping = $pGrouping;
return $this;
}
/**
* Set AutoFilter Rule
*
* @param string $pOperator
* @param string|string[] $pValue
* @param string $pGrouping
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function setRule($pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL, $pValue = '', $pGrouping = null)
{
$this->setOperator($pOperator);
$this->setValue($pValue);
// Only set grouping if it's been passed in as a user-supplied argument,
// otherwise we're calculating it when we setValue() and don't want to overwrite that
// If the user supplies an argumnet for grouping, then on their own head be it
if ($pGrouping !== null) {
$this->setGrouping($pGrouping);
}
return $this;
}
/**
* Get this Rule's AutoFilter Column Parent
*
* @return PHPExcel_Worksheet_AutoFilter_Column
*/
public function getParent()
{
return $this->parent;
}
/**
* Set this Rule's AutoFilter Column Parent
*
* @param PHPExcel_Worksheet_AutoFilter_Column
* @return PHPExcel_Worksheet_AutoFilter_Column_Rule
*/
public function setParent(PHPExcel_Worksheet_AutoFilter_Column $pParent = null)
{
$this->parent = $pParent;
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
if ($key == 'parent') {
// Detach from autofilter column parent
$this->$key = null;
} else {
$this->$key = clone $value;
}
} else {
$this->$key = $value;
}
}
}
}

507
extend/PHPExcel/PHPExcel/Worksheet/BaseDrawing.php

@ -0,0 +1,507 @@
<?php
/**
* PHPExcel_Worksheet_BaseDrawing
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable
{
/**
* Image counter
*
* @var int
*/
private static $imageCounter = 0;
/**
* Image index
*
* @var int
*/
private $imageIndex = 0;
/**
* Name
*
* @var string
*/
protected $name;
/**
* Description
*
* @var string
*/
protected $description;
/**
* Worksheet
*
* @var PHPExcel_Worksheet
*/
protected $worksheet;
/**
* Coordinates
*
* @var string
*/
protected $coordinates;
/**
* Offset X
*
* @var int
*/
protected $offsetX;
/**
* Offset Y
*
* @var int
*/
protected $offsetY;
/**
* Width
*
* @var int
*/
protected $width;
/**
* Height
*
* @var int
*/
protected $height;
/**
* Proportional resize
*
* @var boolean
*/
protected $resizeProportional;
/**
* Rotation
*
* @var int
*/
protected $rotation;
/**
* Shadow
*
* @var PHPExcel_Worksheet_Drawing_Shadow
*/
protected $shadow;
/**
* Create a new PHPExcel_Worksheet_BaseDrawing
*/
public function __construct()
{
// Initialise values
$this->name = '';
$this->description = '';
$this->worksheet = null;
$this->coordinates = 'A1';
$this->offsetX = 0;
$this->offsetY = 0;
$this->width = 0;
$this->height = 0;
$this->resizeProportional = true;
$this->rotation = 0;
$this->shadow = new PHPExcel_Worksheet_Drawing_Shadow();
// Set image index
self::$imageCounter++;
$this->imageIndex = self::$imageCounter;
}
/**
* Get image index
*
* @return int
*/
public function getImageIndex()
{
return $this->imageIndex;
}
/**
* Get Name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set Name
*
* @param string $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setName($pValue = '')
{
$this->name = $pValue;
return $this;
}
/**
* Get Description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set Description
*
* @param string $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setDescription($pValue = '')
{
$this->description = $pValue;
return $this;
}
/**
* Get Worksheet
*
* @return PHPExcel_Worksheet
*/
public function getWorksheet()
{
return $this->worksheet;
}
/**
* Set Worksheet
*
* @param PHPExcel_Worksheet $pValue
* @param bool $pOverrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet?
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setWorksheet(PHPExcel_Worksheet $pValue = null, $pOverrideOld = false)
{
if (is_null($this->worksheet)) {
// Add drawing to PHPExcel_Worksheet
$this->worksheet = $pValue;
$this->worksheet->getCell($this->coordinates);
$this->worksheet->getDrawingCollection()->append($this);
} else {
if ($pOverrideOld) {
// Remove drawing from old PHPExcel_Worksheet
$iterator = $this->worksheet->getDrawingCollection()->getIterator();
while ($iterator->valid()) {
if ($iterator->current()->getHashCode() == $this->getHashCode()) {
$this->worksheet->getDrawingCollection()->offsetUnset($iterator->key());
$this->worksheet = null;
break;
}
}
// Set new PHPExcel_Worksheet
$this->setWorksheet($pValue);
} else {
throw new PHPExcel_Exception("A PHPExcel_Worksheet has already been assigned. Drawings can only exist on one PHPExcel_Worksheet.");
}
}
return $this;
}
/**
* Get Coordinates
*
* @return string
*/
public function getCoordinates()
{
return $this->coordinates;
}
/**
* Set Coordinates
*
* @param string $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setCoordinates($pValue = 'A1')
{
$this->coordinates = $pValue;
return $this;
}
/**
* Get OffsetX
*
* @return int
*/
public function getOffsetX()
{
return $this->offsetX;
}
/**
* Set OffsetX
*
* @param int $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setOffsetX($pValue = 0)
{
$this->offsetX = $pValue;
return $this;
}
/**
* Get OffsetY
*
* @return int
*/
public function getOffsetY()
{
return $this->offsetY;
}
/**
* Set OffsetY
*
* @param int $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setOffsetY($pValue = 0)
{
$this->offsetY = $pValue;
return $this;
}
/**
* Get Width
*
* @return int
*/
public function getWidth()
{
return $this->width;
}
/**
* Set Width
*
* @param int $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setWidth($pValue = 0)
{
// Resize proportional?
if ($this->resizeProportional && $pValue != 0) {
$ratio = $this->height / ($this->width != 0 ? $this->width : 1);
$this->height = round($ratio * $pValue);
}
// Set width
$this->width = $pValue;
return $this;
}
/**
* Get Height
*
* @return int
*/
public function getHeight()
{
return $this->height;
}
/**
* Set Height
*
* @param int $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setHeight($pValue = 0)
{
// Resize proportional?
if ($this->resizeProportional && $pValue != 0) {
$ratio = $this->width / ($this->height != 0 ? $this->height : 1);
$this->width = round($ratio * $pValue);
}
// Set height
$this->height = $pValue;
return $this;
}
/**
* Set width and height with proportional resize
* Example:
* <code>
* $objDrawing->setResizeProportional(true);
* $objDrawing->setWidthAndHeight(160,120);
* </code>
*
* @author Vincent@luo MSN:kele_100@hotmail.com
* @param int $width
* @param int $height
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setWidthAndHeight($width = 0, $height = 0)
{
$xratio = $width / ($this->width != 0 ? $this->width : 1);
$yratio = $height / ($this->height != 0 ? $this->height : 1);
if ($this->resizeProportional && !($width == 0 || $height == 0)) {
if (($xratio * $this->height) < $height) {
$this->height = ceil($xratio * $this->height);
$this->width = $width;
} else {
$this->width = ceil($yratio * $this->width);
$this->height = $height;
}
} else {
$this->width = $width;
$this->height = $height;
}
return $this;
}
/**
* Get ResizeProportional
*
* @return boolean
*/
public function getResizeProportional()
{
return $this->resizeProportional;
}
/**
* Set ResizeProportional
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setResizeProportional($pValue = true)
{
$this->resizeProportional = $pValue;
return $this;
}
/**
* Get Rotation
*
* @return int
*/
public function getRotation()
{
return $this->rotation;
}
/**
* Set Rotation
*
* @param int $pValue
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setRotation($pValue = 0)
{
$this->rotation = $pValue;
return $this;
}
/**
* Get Shadow
*
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function getShadow()
{
return $this->shadow;
}
/**
* Set Shadow
*
* @param PHPExcel_Worksheet_Drawing_Shadow $pValue
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_BaseDrawing
*/
public function setShadow(PHPExcel_Worksheet_Drawing_Shadow $pValue = null)
{
$this->shadow = $pValue;
return $this;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode()
{
return md5(
$this->name .
$this->description .
$this->worksheet->getHashCode() .
$this->coordinates .
$this->offsetX .
$this->offsetY .
$this->width .
$this->height .
$this->rotation .
$this->shadow->getHashCode() .
__CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

88
extend/PHPExcel/PHPExcel/Worksheet/CellIterator.php

@ -0,0 +1,88 @@
<?php
/**
* PHPExcel_Worksheet_CellIterator
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
abstract class PHPExcel_Worksheet_CellIterator
{
/**
* PHPExcel_Worksheet to iterate
*
* @var PHPExcel_Worksheet
*/
protected $subject;
/**
* Current iterator position
*
* @var mixed
*/
protected $position = null;
/**
* Iterate only existing cells
*
* @var boolean
*/
protected $onlyExistingCells = false;
/**
* Destructor
*/
public function __destruct()
{
unset($this->subject);
}
/**
* Get loop only existing cells
*
* @return boolean
*/
public function getIterateOnlyExistingCells()
{
return $this->onlyExistingCells;
}
/**
* Validate start/end values for "IterateOnlyExistingCells" mode, and adjust if necessary
*
* @throws PHPExcel_Exception
*/
abstract protected function adjustForExistingOnlyRange();
/**
* Set the iterator to loop only existing cells
*
* @param boolean $value
* @throws PHPExcel_Exception
*/
public function setIterateOnlyExistingCells($value = true)
{
$this->onlyExistingCells = (boolean) $value;
$this->adjustForExistingOnlyRange();
}
}

86
extend/PHPExcel/PHPExcel/Worksheet/Column.php

@ -0,0 +1,86 @@
<?php
/**
* PHPExcel_Worksheet_Column
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_Column
{
/**
* PHPExcel_Worksheet
*
* @var PHPExcel_Worksheet
*/
private $parent;
/**
* Column index
*
* @var string
*/
private $columnIndex;
/**
* Create a new column
*
* @param PHPExcel_Worksheet $parent
* @param string $columnIndex
*/
public function __construct(PHPExcel_Worksheet $parent = null, $columnIndex = 'A')
{
// Set parent and column index
$this->parent = $parent;
$this->columnIndex = $columnIndex;
}
/**
* Destructor
*/
public function __destruct()
{
unset($this->parent);
}
/**
* Get column index
*
* @return string
*/
public function getColumnIndex()
{
return $this->columnIndex;
}
/**
* Get cell iterator
*
* @param integer $startRow The row number at which to start iterating
* @param integer $endRow Optionally, the row number at which to stop iterating
* @return PHPExcel_Worksheet_CellIterator
*/
public function getCellIterator($startRow = 1, $endRow = null)
{
return new PHPExcel_Worksheet_ColumnCellIterator($this->parent, $this->columnIndex, $startRow, $endRow);
}
}

216
extend/PHPExcel/PHPExcel/Worksheet/ColumnCellIterator.php

@ -0,0 +1,216 @@
<?php
/**
* PHPExcel_Worksheet_ColumnCellIterator
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_ColumnCellIterator extends PHPExcel_Worksheet_CellIterator implements Iterator
{
/**
* Column index
*
* @var string
*/
protected $columnIndex;
/**
* Start position
*
* @var int
*/
protected $startRow = 1;
/**
* End position
*
* @var int
*/
protected $endRow = 1;
/**
* Create a new row iterator
*
* @param PHPExcel_Worksheet $subject The worksheet to iterate over
* @param string $columnIndex The column that we want to iterate
* @param integer $startRow The row number at which to start iterating
* @param integer $endRow Optionally, the row number at which to stop iterating
*/
public function __construct(PHPExcel_Worksheet $subject = null, $columnIndex = 'A', $startRow = 1, $endRow = null)
{
// Set subject
$this->subject = $subject;
$this->columnIndex = PHPExcel_Cell::columnIndexFromString($columnIndex) - 1;
$this->resetEnd($endRow);
$this->resetStart($startRow);
}
/**
* Destructor
*/
public function __destruct()
{
unset($this->subject);
}
/**
* (Re)Set the start row and the current row pointer
*
* @param integer $startRow The row number at which to start iterating
* @return PHPExcel_Worksheet_ColumnCellIterator
* @throws PHPExcel_Exception
*/
public function resetStart($startRow = 1)
{
$this->startRow = $startRow;
$this->adjustForExistingOnlyRange();
$this->seek($startRow);
return $this;
}
/**
* (Re)Set the end row
*
* @param integer $endRow The row number at which to stop iterating
* @return PHPExcel_Worksheet_ColumnCellIterator
* @throws PHPExcel_Exception
*/
public function resetEnd($endRow = null)
{
$this->endRow = ($endRow) ? $endRow : $this->subject->getHighestRow();
$this->adjustForExistingOnlyRange();
return $this;
}
/**
* Set the row pointer to the selected row
*
* @param integer $row The row number to set the current pointer at
* @return PHPExcel_Worksheet_ColumnCellIterator
* @throws PHPExcel_Exception
*/
public function seek($row = 1)
{
if (($row < $this->startRow) || ($row > $this->endRow)) {
throw new PHPExcel_Exception("Row $row is out of range ({$this->startRow} - {$this->endRow})");
} elseif ($this->onlyExistingCells && !($this->subject->cellExistsByColumnAndRow($this->columnIndex, $row))) {
throw new PHPExcel_Exception('In "IterateOnlyExistingCells" mode and Cell does not exist');
}
$this->position = $row;
return $this;
}
/**
* Rewind the iterator to the starting row
*/
public function rewind()
{
$this->position = $this->startRow;
}
/**
* Return the current cell in this worksheet column
*
* @return PHPExcel_Worksheet_Row
*/
public function current()
{
return $this->subject->getCellByColumnAndRow($this->columnIndex, $this->position);
}
/**
* Return the current iterator key
*
* @return int
*/
public function key()
{
return $this->position;
}
/**
* Set the iterator to its next value
*/
public function next()
{
do {
++$this->position;
} while (($this->onlyExistingCells) &&
(!$this->subject->cellExistsByColumnAndRow($this->columnIndex, $this->position)) &&
($this->position <= $this->endRow));
}
/**
* Set the iterator to its previous value
*/
public function prev()
{
if ($this->position <= $this->startRow) {
throw new PHPExcel_Exception("Row is already at the beginning of range ({$this->startRow} - {$this->endRow})");
}
do {
--$this->position;
} while (($this->onlyExistingCells) &&
(!$this->subject->cellExistsByColumnAndRow($this->columnIndex, $this->position)) &&
($this->position >= $this->startRow));
}
/**
* Indicate if more rows exist in the worksheet range of rows that we're iterating
*
* @return boolean
*/
public function valid()
{
return $this->position <= $this->endRow;
}
/**
* Validate start/end values for "IterateOnlyExistingCells" mode, and adjust if necessary
*
* @throws PHPExcel_Exception
*/
protected function adjustForExistingOnlyRange()
{
if ($this->onlyExistingCells) {
while ((!$this->subject->cellExistsByColumnAndRow($this->columnIndex, $this->startRow)) &&
($this->startRow <= $this->endRow)) {
++$this->startRow;
}
if ($this->startRow > $this->endRow) {
throw new PHPExcel_Exception('No cells exist within the specified range');
}
while ((!$this->subject->cellExistsByColumnAndRow($this->columnIndex, $this->endRow)) &&
($this->endRow >= $this->startRow)) {
--$this->endRow;
}
if ($this->endRow < $this->startRow) {
throw new PHPExcel_Exception('No cells exist within the specified range');
}
}
}
}

132
extend/PHPExcel/PHPExcel/Worksheet/ColumnDimension.php

@ -0,0 +1,132 @@
<?php
/**
* PHPExcel_Worksheet_ColumnDimension
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_ColumnDimension extends PHPExcel_Worksheet_Dimension
{
/**
* Column index
*
* @var int
*/
private $columnIndex;
/**
* Column width
*
* When this is set to a negative value, the column width should be ignored by IWriter
*
* @var double
*/
private $width = -1;
/**
* Auto size?
*
* @var bool
*/
private $autoSize = false;
/**
* Create a new PHPExcel_Worksheet_ColumnDimension
*
* @param string $pIndex Character column index
*/
public function __construct($pIndex = 'A')
{
// Initialise values
$this->columnIndex = $pIndex;
// set dimension as unformatted by default
parent::__construct(0);
}
/**
* Get ColumnIndex
*
* @return string
*/
public function getColumnIndex()
{
return $this->columnIndex;
}
/**
* Set ColumnIndex
*
* @param string $pValue
* @return PHPExcel_Worksheet_ColumnDimension
*/
public function setColumnIndex($pValue)
{
$this->columnIndex = $pValue;
return $this;
}
/**
* Get Width
*
* @return double
*/
public function getWidth()
{
return $this->width;
}
/**
* Set Width
*
* @param double $pValue
* @return PHPExcel_Worksheet_ColumnDimension
*/
public function setWidth($pValue = -1)
{
$this->width = $pValue;
return $this;
}
/**
* Get Auto Size
*
* @return bool
*/
public function getAutoSize()
{
return $this->autoSize;
}
/**
* Set Auto Size
*
* @param bool $pValue
* @return PHPExcel_Worksheet_ColumnDimension
*/
public function setAutoSize($pValue = false)
{
$this->autoSize = $pValue;
return $this;
}
}

201
extend/PHPExcel/PHPExcel/Worksheet/ColumnIterator.php

@ -0,0 +1,201 @@
<?php
/**
* PHPExcel_Worksheet_ColumnIterator
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_ColumnIterator implements Iterator
{
/**
* PHPExcel_Worksheet to iterate
*
* @var PHPExcel_Worksheet
*/
private $subject;
/**
* Current iterator position
*
* @var int
*/
private $position = 0;
/**
* Start position
*
* @var int
*/
private $startColumn = 0;
/**
* End position
*
* @var int
*/
private $endColumn = 0;
/**
* Create a new column iterator
*
* @param PHPExcel_Worksheet $subject The worksheet to iterate over
* @param string $startColumn The column address at which to start iterating
* @param string $endColumn Optionally, the column address at which to stop iterating
*/
public function __construct(PHPExcel_Worksheet $subject = null, $startColumn = 'A', $endColumn = null)
{
// Set subject
$this->subject = $subject;
$this->resetEnd($endColumn);
$this->resetStart($startColumn);
}
/**
* Destructor
*/
public function __destruct()
{
unset($this->subject);
}
/**
* (Re)Set the start column and the current column pointer
*
* @param integer $startColumn The column address at which to start iterating
* @return PHPExcel_Worksheet_ColumnIterator
* @throws PHPExcel_Exception
*/
public function resetStart($startColumn = 'A')
{
$startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumn) - 1;
if ($startColumnIndex > PHPExcel_Cell::columnIndexFromString($this->subject->getHighestColumn()) - 1) {
throw new PHPExcel_Exception("Start column ({$startColumn}) is beyond highest column ({$this->subject->getHighestColumn()})");
}
$this->startColumn = $startColumnIndex;
if ($this->endColumn < $this->startColumn) {
$this->endColumn = $this->startColumn;
}
$this->seek($startColumn);
return $this;
}
/**
* (Re)Set the end column
*
* @param string $endColumn The column address at which to stop iterating
* @return PHPExcel_Worksheet_ColumnIterator
*/
public function resetEnd($endColumn = null)
{
$endColumn = ($endColumn) ? $endColumn : $this->subject->getHighestColumn();
$this->endColumn = PHPExcel_Cell::columnIndexFromString($endColumn) - 1;
return $this;
}
/**
* Set the column pointer to the selected column
*
* @param string $column The column address to set the current pointer at
* @return PHPExcel_Worksheet_ColumnIterator
* @throws PHPExcel_Exception
*/
public function seek($column = 'A')
{
$column = PHPExcel_Cell::columnIndexFromString($column) - 1;
if (($column < $this->startColumn) || ($column > $this->endColumn)) {
throw new PHPExcel_Exception("Column $column is out of range ({$this->startColumn} - {$this->endColumn})");
}
$this->position = $column;
return $this;
}
/**
* Rewind the iterator to the starting column
*/
public function rewind()
{
$this->position = $this->startColumn;
}
/**
* Return the current column in this worksheet
*
* @return PHPExcel_Worksheet_Column
*/
public function current()
{
return new PHPExcel_Worksheet_Column($this->subject, PHPExcel_Cell::stringFromColumnIndex($this->position));
}
/**
* Return the current iterator key
*
* @return string
*/
public function key()
{
return PHPExcel_Cell::stringFromColumnIndex($this->position);
}
/**
* Set the iterator to its next value
*/
public function next()
{
++$this->position;
}
/**
* Set the iterator to its previous value
*
* @throws PHPExcel_Exception
*/
public function prev()
{
if ($this->position <= $this->startColumn) {
throw new PHPExcel_Exception(
"Column is already at the beginning of range (" .
PHPExcel_Cell::stringFromColumnIndex($this->endColumn) . " - " .
PHPExcel_Cell::stringFromColumnIndex($this->endColumn) . ")"
);
}
--$this->position;
}
/**
* Indicate if more columns exist in the worksheet range of columns that we're iterating
*
* @return boolean
*/
public function valid()
{
return $this->position <= $this->endColumn;
}
}

178
extend/PHPExcel/PHPExcel/Worksheet/Dimension.php

@ -0,0 +1,178 @@
<?php
/**
* PHPExcel_Worksheet_Dimension
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
abstract class PHPExcel_Worksheet_Dimension
{
/**
* Visible?
*
* @var bool
*/
private $visible = true;
/**
* Outline level
*
* @var int
*/
private $outlineLevel = 0;
/**
* Collapsed
*
* @var bool
*/
private $collapsed = false;
/**
* Index to cellXf. Null value means row has no explicit cellXf format.
*
* @var int|null
*/
private $xfIndex;
/**
* Create a new PHPExcel_Worksheet_Dimension
*
* @param int $pIndex Numeric row index
*/
public function __construct($initialValue = null)
{
// set dimension as unformatted by default
$this->xfIndex = $initialValue;
}
/**
* Get Visible
*
* @return bool
*/
public function getVisible()
{
return $this->visible;
}
/**
* Set Visible
*
* @param bool $pValue
* @return PHPExcel_Worksheet_Dimension
*/
public function setVisible($pValue = true)
{
$this->visible = $pValue;
return $this;
}
/**
* Get Outline Level
*
* @return int
*/
public function getOutlineLevel()
{
return $this->outlineLevel;
}
/**
* Set Outline Level
*
* Value must be between 0 and 7
*
* @param int $pValue
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_Dimension
*/
public function setOutlineLevel($pValue)
{
if ($pValue < 0 || $pValue > 7) {
throw new PHPExcel_Exception("Outline level must range between 0 and 7.");
}
$this->outlineLevel = $pValue;
return $this;
}
/**
* Get Collapsed
*
* @return bool
*/
public function getCollapsed()
{
return $this->collapsed;
}
/**
* Set Collapsed
*
* @param bool $pValue
* @return PHPExcel_Worksheet_Dimension
*/
public function setCollapsed($pValue = true)
{
$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_Dimension
*/
public function setXfIndex($pValue = 0)
{
$this->xfIndex = $pValue;
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

147
extend/PHPExcel/PHPExcel/Worksheet/Drawing.php

@ -0,0 +1,147 @@
<?php
/**
* PHPExcel_Worksheet_Drawing
*
* Copyright (c) 2006 - 2015 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_Worksheet_Drawing
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable
{
/**
* Path
*
* @var string
*/
private $path;
/**
* Create a new PHPExcel_Worksheet_Drawing
*/
public function __construct()
{
// Initialise values
$this->path = '';
// Initialize parent
parent::__construct();
}
/**
* Get Filename
*
* @return string
*/
public function getFilename()
{
return basename($this->path);
}
/**
* Get indexed filename (using image index)
*
* @return string
*/
public function getIndexedFilename()
{
$fileName = $this->getFilename();
$fileName = str_replace(' ', '_', $fileName);
return str_replace('.' . $this->getExtension(), '', $fileName) . $this->getImageIndex() . '.' . $this->getExtension();
}
/**
* Get Extension
*
* @return string
*/
public function getExtension()
{
$exploded = explode(".", basename($this->path));
return $exploded[count($exploded) - 1];
}
/**
* Get Path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set Path
*
* @param string $pValue File path
* @param boolean $pVerifyFile Verify file
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_Drawing
*/
public function setPath($pValue = '', $pVerifyFile = true)
{
if ($pVerifyFile) {
if (file_exists($pValue)) {
$this->path = $pValue;
if ($this->width == 0 && $this->height == 0) {
// Get width/height
list($this->width, $this->height) = getimagesize($pValue);
}
} else {
throw new PHPExcel_Exception("File $pValue not found!");
}
} else {
$this->path = $pValue;
}
return $this;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode()
{
return md5(
$this->path .
parent::getHashCode() .
__CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

296
extend/PHPExcel/PHPExcel/Worksheet/Drawing/Shadow.php

@ -0,0 +1,296 @@
<?php
/**
* PHPExcel_Worksheet_Drawing_Shadow
*
* Copyright (c) 2006 - 2015 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_Worksheet_Drawing
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable
{
/* Shadow alignment */
const SHADOW_BOTTOM = 'b';
const SHADOW_BOTTOM_LEFT = 'bl';
const SHADOW_BOTTOM_RIGHT = 'br';
const SHADOW_CENTER = 'ctr';
const SHADOW_LEFT = 'l';
const SHADOW_TOP = 't';
const SHADOW_TOP_LEFT = 'tl';
const SHADOW_TOP_RIGHT = 'tr';
/**
* Visible
*
* @var boolean
*/
private $visible;
/**
* Blur radius
*
* Defaults to 6
*
* @var int
*/
private $blurRadius;
/**
* Shadow distance
*
* Defaults to 2
*
* @var int
*/
private $distance;
/**
* Shadow direction (in degrees)
*
* @var int
*/
private $direction;
/**
* Shadow alignment
*
* @var int
*/
private $alignment;
/**
* Color
*
* @var PHPExcel_Style_Color
*/
private $color;
/**
* Alpha
*
* @var int
*/
private $alpha;
/**
* Create a new PHPExcel_Worksheet_Drawing_Shadow
*/
public function __construct()
{
// Initialise values
$this->visible = false;
$this->blurRadius = 6;
$this->distance = 2;
$this->direction = 0;
$this->alignment = PHPExcel_Worksheet_Drawing_Shadow::SHADOW_BOTTOM_RIGHT;
$this->color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK);
$this->alpha = 50;
}
/**
* Get Visible
*
* @return boolean
*/
public function getVisible()
{
return $this->visible;
}
/**
* Set Visible
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function setVisible($pValue = false)
{
$this->visible = $pValue;
return $this;
}
/**
* Get Blur radius
*
* @return int
*/
public function getBlurRadius()
{
return $this->blurRadius;
}
/**
* Set Blur radius
*
* @param int $pValue
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function setBlurRadius($pValue = 6)
{
$this->blurRadius = $pValue;
return $this;
}
/**
* Get Shadow distance
*
* @return int
*/
public function getDistance()
{
return $this->distance;
}
/**
* Set Shadow distance
*
* @param int $pValue
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function setDistance($pValue = 2)
{
$this->distance = $pValue;
return $this;
}
/**
* Get Shadow direction (in degrees)
*
* @return int
*/
public function getDirection()
{
return $this->direction;
}
/**
* Set Shadow direction (in degrees)
*
* @param int $pValue
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function setDirection($pValue = 0)
{
$this->direction = $pValue;
return $this;
}
/**
* Get Shadow alignment
*
* @return int
*/
public function getAlignment()
{
return $this->alignment;
}
/**
* Set Shadow alignment
*
* @param int $pValue
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function setAlignment($pValue = 0)
{
$this->alignment = $pValue;
return $this;
}
/**
* Get Color
*
* @return PHPExcel_Style_Color
*/
public function getColor()
{
return $this->color;
}
/**
* Set Color
*
* @param PHPExcel_Style_Color $pValue
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function setColor(PHPExcel_Style_Color $pValue = null)
{
$this->color = $pValue;
return $this;
}
/**
* Get Alpha
*
* @return int
*/
public function getAlpha()
{
return $this->alpha;
}
/**
* Set Alpha
*
* @param int $pValue
* @return PHPExcel_Worksheet_Drawing_Shadow
*/
public function setAlpha($pValue = 0)
{
$this->alpha = $pValue;
return $this;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode()
{
return md5(
($this->visible ? 't' : 'f') .
$this->blurRadius .
$this->distance .
$this->direction .
$this->alignment .
$this->color->getHashCode() .
$this->alpha .
__CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

494
extend/PHPExcel/PHPExcel/Worksheet/HeaderFooter.php

@ -0,0 +1,494 @@
<?php
/**
* PHPExcel_Worksheet_HeaderFooter
*
* Copyright (c) 2006 - 2015 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,241 write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category PHPExcel
* @package PHPExcel_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*
* <code>
* Header/Footer Formatting Syntax taken from Office Open XML Part 4 - Markup Language Reference, page 1970:
*
* There are a number of formatting codes that can be written inline with the actual header / footer text, which
* affect the formatting in the header or footer.
*
* Example: This example shows the text "Center Bold Header" on the first line (center section), and the date on
* the second line (center section).
* &CCenter &"-,Bold"Bold&"-,Regular"Header_x000A_&D
*
* General Rules:
* There is no required order in which these codes must appear.
*
* The first occurrence of the following codes turns the formatting ON, the second occurrence turns it OFF again:
* - strikethrough
* - superscript
* - subscript
* Superscript and subscript cannot both be ON at same time. Whichever comes first wins and the other is ignored,
* while the first is ON.
* &L - code for "left section" (there are three header / footer locations, "left", "center", and "right"). When
* two or more occurrences of this section marker exist, the contents from all markers are concatenated, in the
* order of appearance, and placed into the left section.
* &P - code for "current page #"
* &N - code for "total pages"
* &font size - code for "text font size", where font size is a font size in points.
* &K - code for "text font color"
* RGB Color is specified as RRGGBB
* Theme Color is specifed as TTSNN where TT is the theme color Id, S is either "+" or "-" of the tint/shade
* value, NN is the tint/shade value.
* &S - code for "text strikethrough" on / off
* &X - code for "text super script" on / off
* &Y - code for "text subscript" on / off
* &C - code for "center section". When two or more occurrences of this section marker exist, the contents
* from all markers are concatenated, in the order of appearance, and placed into the center section.
*
* &D - code for "date"
* &T - code for "time"
* &G - code for "picture as background"
* &U - code for "text single underline"
* &E - code for "double underline"
* &R - code for "right section". When two or more occurrences of this section marker exist, the contents
* from all markers are concatenated, in the order of appearance, and placed into the right section.
* &Z - code for "this workbook's file path"
* &F - code for "this workbook's file name"
* &A - code for "sheet tab name"
* &+ - code for add to page #.
* &- - code for subtract from page #.
* &"font name,font type" - code for "text font name" and "text font type", where font name and font type
* are strings specifying the name and type of the font, separated by a comma. When a hyphen appears in font
* name, it means "none specified". Both of font name and font type can be localized values.
* &"-,Bold" - code for "bold font style"
* &B - also means "bold font style".
* &"-,Regular" - code for "regular font style"
* &"-,Italic" - code for "italic font style"
* &I - also means "italic font style"
* &"-,Bold Italic" code for "bold italic font style"
* &O - code for "outline style"
* &H - code for "shadow style"
* </code>
*
*/
class PHPExcel_Worksheet_HeaderFooter
{
/* Header/footer image location */
const IMAGE_HEADER_LEFT = 'LH';
const IMAGE_HEADER_CENTER = 'CH';
const IMAGE_HEADER_RIGHT = 'RH';
const IMAGE_FOOTER_LEFT = 'LF';
const IMAGE_FOOTER_CENTER = 'CF';
const IMAGE_FOOTER_RIGHT = 'RF';
/**
* OddHeader
*
* @var string
*/
private $oddHeader = '';
/**
* OddFooter
*
* @var string
*/
private $oddFooter = '';
/**
* EvenHeader
*
* @var string
*/
private $evenHeader = '';
/**
* EvenFooter
*
* @var string
*/
private $evenFooter = '';
/**
* FirstHeader
*
* @var string
*/
private $firstHeader = '';
/**
* FirstFooter
*
* @var string
*/
private $firstFooter = '';
/**
* Different header for Odd/Even, defaults to false
*
* @var boolean
*/
private $differentOddEven = false;
/**
* Different header for first page, defaults to false
*
* @var boolean
*/
private $differentFirst = false;
/**
* Scale with document, defaults to true
*
* @var boolean
*/
private $scaleWithDocument = true;
/**
* Align with margins, defaults to true
*
* @var boolean
*/
private $alignWithMargins = true;
/**
* Header/footer images
*
* @var PHPExcel_Worksheet_HeaderFooterDrawing[]
*/
private $headerFooterImages = array();
/**
* Create a new PHPExcel_Worksheet_HeaderFooter
*/
public function __construct()
{
}
/**
* Get OddHeader
*
* @return string
*/
public function getOddHeader()
{
return $this->oddHeader;
}
/**
* Set OddHeader
*
* @param string $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setOddHeader($pValue)
{
$this->oddHeader = $pValue;
return $this;
}
/**
* Get OddFooter
*
* @return string
*/
public function getOddFooter()
{
return $this->oddFooter;
}
/**
* Set OddFooter
*
* @param string $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setOddFooter($pValue)
{
$this->oddFooter = $pValue;
return $this;
}
/**
* Get EvenHeader
*
* @return string
*/
public function getEvenHeader()
{
return $this->evenHeader;
}
/**
* Set EvenHeader
*
* @param string $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setEvenHeader($pValue)
{
$this->evenHeader = $pValue;
return $this;
}
/**
* Get EvenFooter
*
* @return string
*/
public function getEvenFooter()
{
return $this->evenFooter;
}
/**
* Set EvenFooter
*
* @param string $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setEvenFooter($pValue)
{
$this->evenFooter = $pValue;
return $this;
}
/**
* Get FirstHeader
*
* @return string
*/
public function getFirstHeader()
{
return $this->firstHeader;
}
/**
* Set FirstHeader
*
* @param string $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setFirstHeader($pValue)
{
$this->firstHeader = $pValue;
return $this;
}
/**
* Get FirstFooter
*
* @return string
*/
public function getFirstFooter()
{
return $this->firstFooter;
}
/**
* Set FirstFooter
*
* @param string $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setFirstFooter($pValue)
{
$this->firstFooter = $pValue;
return $this;
}
/**
* Get DifferentOddEven
*
* @return boolean
*/
public function getDifferentOddEven()
{
return $this->differentOddEven;
}
/**
* Set DifferentOddEven
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setDifferentOddEven($pValue = false)
{
$this->differentOddEven = $pValue;
return $this;
}
/**
* Get DifferentFirst
*
* @return boolean
*/
public function getDifferentFirst()
{
return $this->differentFirst;
}
/**
* Set DifferentFirst
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setDifferentFirst($pValue = false)
{
$this->differentFirst = $pValue;
return $this;
}
/**
* Get ScaleWithDocument
*
* @return boolean
*/
public function getScaleWithDocument()
{
return $this->scaleWithDocument;
}
/**
* Set ScaleWithDocument
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setScaleWithDocument($pValue = true)
{
$this->scaleWithDocument = $pValue;
return $this;
}
/**
* Get AlignWithMargins
*
* @return boolean
*/
public function getAlignWithMargins()
{
return $this->alignWithMargins;
}
/**
* Set AlignWithMargins
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setAlignWithMargins($pValue = true)
{
$this->alignWithMargins = $pValue;
return $this;
}
/**
* Add header/footer image
*
* @param PHPExcel_Worksheet_HeaderFooterDrawing $image
* @param string $location
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function addImage(PHPExcel_Worksheet_HeaderFooterDrawing $image = null, $location = self::IMAGE_HEADER_LEFT)
{
$this->headerFooterImages[$location] = $image;
return $this;
}
/**
* Remove header/footer image
*
* @param string $location
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function removeImage($location = self::IMAGE_HEADER_LEFT)
{
if (isset($this->headerFooterImages[$location])) {
unset($this->headerFooterImages[$location]);
}
return $this;
}
/**
* Set header/footer images
*
* @param PHPExcel_Worksheet_HeaderFooterDrawing[] $images
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_HeaderFooter
*/
public function setImages($images)
{
if (!is_array($images)) {
throw new PHPExcel_Exception('Invalid parameter!');
}
$this->headerFooterImages = $images;
return $this;
}
/**
* Get header/footer images
*
* @return PHPExcel_Worksheet_HeaderFooterDrawing[]
*/
public function getImages()
{
// Sort array
$images = array();
if (isset($this->headerFooterImages[self::IMAGE_HEADER_LEFT])) {
$images[self::IMAGE_HEADER_LEFT] = $this->headerFooterImages[self::IMAGE_HEADER_LEFT];
}
if (isset($this->headerFooterImages[self::IMAGE_HEADER_CENTER])) {
$images[self::IMAGE_HEADER_CENTER] = $this->headerFooterImages[self::IMAGE_HEADER_CENTER];
}
if (isset($this->headerFooterImages[self::IMAGE_HEADER_RIGHT])) {
$images[self::IMAGE_HEADER_RIGHT] = $this->headerFooterImages[self::IMAGE_HEADER_RIGHT];
}
if (isset($this->headerFooterImages[self::IMAGE_FOOTER_LEFT])) {
$images[self::IMAGE_FOOTER_LEFT] = $this->headerFooterImages[self::IMAGE_FOOTER_LEFT];
}
if (isset($this->headerFooterImages[self::IMAGE_FOOTER_CENTER])) {
$images[self::IMAGE_FOOTER_CENTER] = $this->headerFooterImages[self::IMAGE_FOOTER_CENTER];
}
if (isset($this->headerFooterImages[self::IMAGE_FOOTER_RIGHT])) {
$images[self::IMAGE_FOOTER_RIGHT] = $this->headerFooterImages[self::IMAGE_FOOTER_RIGHT];
}
$this->headerFooterImages = $images;
return $this->headerFooterImages;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

361
extend/PHPExcel/PHPExcel/Worksheet/HeaderFooterDrawing.php

@ -0,0 +1,361 @@
<?php
/**
* PHPExcel_Worksheet_HeaderFooterDrawing
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing implements PHPExcel_IComparable
{
/**
* Path
*
* @var string
*/
private $path;
/**
* Name
*
* @var string
*/
protected $name;
/**
* Offset X
*
* @var int
*/
protected $offsetX;
/**
* Offset Y
*
* @var int
*/
protected $offsetY;
/**
* Width
*
* @var int
*/
protected $width;
/**
* Height
*
* @var int
*/
protected $height;
/**
* Proportional resize
*
* @var boolean
*/
protected $resizeProportional;
/**
* Create a new PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function __construct()
{
// Initialise values
$this->path = '';
$this->name = '';
$this->offsetX = 0;
$this->offsetY = 0;
$this->width = 0;
$this->height = 0;
$this->resizeProportional = true;
}
/**
* Get Name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set Name
*
* @param string $pValue
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setName($pValue = '')
{
$this->name = $pValue;
return $this;
}
/**
* Get OffsetX
*
* @return int
*/
public function getOffsetX()
{
return $this->offsetX;
}
/**
* Set OffsetX
*
* @param int $pValue
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setOffsetX($pValue = 0)
{
$this->offsetX = $pValue;
return $this;
}
/**
* Get OffsetY
*
* @return int
*/
public function getOffsetY()
{
return $this->offsetY;
}
/**
* Set OffsetY
*
* @param int $pValue
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setOffsetY($pValue = 0)
{
$this->offsetY = $pValue;
return $this;
}
/**
* Get Width
*
* @return int
*/
public function getWidth()
{
return $this->width;
}
/**
* Set Width
*
* @param int $pValue
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setWidth($pValue = 0)
{
// Resize proportional?
if ($this->resizeProportional && $pValue != 0) {
$ratio = $this->width / $this->height;
$this->height = round($ratio * $pValue);
}
// Set width
$this->width = $pValue;
return $this;
}
/**
* Get Height
*
* @return int
*/
public function getHeight()
{
return $this->height;
}
/**
* Set Height
*
* @param int $pValue
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setHeight($pValue = 0)
{
// Resize proportional?
if ($this->resizeProportional && $pValue != 0) {
$ratio = $this->width / $this->height;
$this->width = round($ratio * $pValue);
}
// Set height
$this->height = $pValue;
return $this;
}
/**
* Set width and height with proportional resize
* Example:
* <code>
* $objDrawing->setResizeProportional(true);
* $objDrawing->setWidthAndHeight(160,120);
* </code>
*
* @author Vincent@luo MSN:kele_100@hotmail.com
* @param int $width
* @param int $height
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setWidthAndHeight($width = 0, $height = 0)
{
$xratio = $width / $this->width;
$yratio = $height / $this->height;
if ($this->resizeProportional && !($width == 0 || $height == 0)) {
if (($xratio * $this->height) < $height) {
$this->height = ceil($xratio * $this->height);
$this->width = $width;
} else {
$this->width = ceil($yratio * $this->width);
$this->height = $height;
}
}
return $this;
}
/**
* Get ResizeProportional
*
* @return boolean
*/
public function getResizeProportional()
{
return $this->resizeProportional;
}
/**
* Set ResizeProportional
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setResizeProportional($pValue = true)
{
$this->resizeProportional = $pValue;
return $this;
}
/**
* Get Filename
*
* @return string
*/
public function getFilename()
{
return basename($this->path);
}
/**
* Get Extension
*
* @return string
*/
public function getExtension()
{
$parts = explode(".", basename($this->path));
return end($parts);
}
/**
* Get Path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set Path
*
* @param string $pValue File path
* @param boolean $pVerifyFile Verify file
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_HeaderFooterDrawing
*/
public function setPath($pValue = '', $pVerifyFile = true)
{
if ($pVerifyFile) {
if (file_exists($pValue)) {
$this->path = $pValue;
if ($this->width == 0 && $this->height == 0) {
// Get width/height
list($this->width, $this->height) = getimagesize($pValue);
}
} else {
throw new PHPExcel_Exception("File $pValue not found!");
}
} else {
$this->path = $pValue;
}
return $this;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode()
{
return md5(
$this->path .
$this->name .
$this->offsetX .
$this->offsetY .
$this->width .
$this->height .
__CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

201
extend/PHPExcel/PHPExcel/Worksheet/MemoryDrawing.php

@ -0,0 +1,201 @@
<?php
/**
* PHPExcel_Worksheet_MemoryDrawing
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable
{
/* Rendering functions */
const RENDERING_DEFAULT = 'imagepng';
const RENDERING_PNG = 'imagepng';
const RENDERING_GIF = 'imagegif';
const RENDERING_JPEG = 'imagejpeg';
/* MIME types */
const MIMETYPE_DEFAULT = 'image/png';
const MIMETYPE_PNG = 'image/png';
const MIMETYPE_GIF = 'image/gif';
const MIMETYPE_JPEG = 'image/jpeg';
/**
* Image resource
*
* @var resource
*/
private $imageResource;
/**
* Rendering function
*
* @var string
*/
private $renderingFunction;
/**
* Mime type
*
* @var string
*/
private $mimeType;
/**
* Unique name
*
* @var string
*/
private $uniqueName;
/**
* Create a new PHPExcel_Worksheet_MemoryDrawing
*/
public function __construct()
{
// Initialise values
$this->imageResource = null;
$this->renderingFunction = self::RENDERING_DEFAULT;
$this->mimeType = self::MIMETYPE_DEFAULT;
$this->uniqueName = md5(rand(0, 9999). time() . rand(0, 9999));
// Initialize parent
parent::__construct();
}
/**
* Get image resource
*
* @return resource
*/
public function getImageResource()
{
return $this->imageResource;
}
/**
* Set image resource
*
* @param $value resource
* @return PHPExcel_Worksheet_MemoryDrawing
*/
public function setImageResource($value = null)
{
$this->imageResource = $value;
if (!is_null($this->imageResource)) {
// Get width/height
$this->width = imagesx($this->imageResource);
$this->height = imagesy($this->imageResource);
}
return $this;
}
/**
* Get rendering function
*
* @return string
*/
public function getRenderingFunction()
{
return $this->renderingFunction;
}
/**
* Set rendering function
*
* @param string $value
* @return PHPExcel_Worksheet_MemoryDrawing
*/
public function setRenderingFunction($value = PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT)
{
$this->renderingFunction = $value;
return $this;
}
/**
* Get mime type
*
* @return string
*/
public function getMimeType()
{
return $this->mimeType;
}
/**
* Set mime type
*
* @param string $value
* @return PHPExcel_Worksheet_MemoryDrawing
*/
public function setMimeType($value = PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_DEFAULT)
{
$this->mimeType = $value;
return $this;
}
/**
* Get indexed filename (using image index)
*
* @return string
*/
public function getIndexedFilename()
{
$extension = strtolower($this->getMimeType());
$extension = explode('/', $extension);
$extension = $extension[1];
return $this->uniqueName . $this->getImageIndex() . '.' . $extension;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode()
{
return md5(
$this->renderingFunction .
$this->mimeType .
$this->uniqueName .
parent::getHashCode() .
__CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

233
extend/PHPExcel/PHPExcel/Worksheet/PageMargins.php

@ -0,0 +1,233 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Worksheet_PageMargins
*
* @category PHPExcel
* @package PHPExcel_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Worksheet_PageMargins
{
/**
* Left
*
* @var double
*/
private $left = 0.7;
/**
* Right
*
* @var double
*/
private $right = 0.7;
/**
* Top
*
* @var double
*/
private $top = 0.75;
/**
* Bottom
*
* @var double
*/
private $bottom = 0.75;
/**
* Header
*
* @var double
*/
private $header = 0.3;
/**
* Footer
*
* @var double
*/
private $footer = 0.3;
/**
* Create a new PHPExcel_Worksheet_PageMargins
*/
public function __construct()
{
}
/**
* Get Left
*
* @return double
*/
public function getLeft()
{
return $this->left;
}
/**
* Set Left
*
* @param double $pValue
* @return PHPExcel_Worksheet_PageMargins
*/
public function setLeft($pValue)
{
$this->left = $pValue;
return $this;
}
/**
* Get Right
*
* @return double
*/
public function getRight()
{
return $this->right;
}
/**
* Set Right
*
* @param double $pValue
* @return PHPExcel_Worksheet_PageMargins
*/
public function setRight($pValue)
{
$this->right = $pValue;
return $this;
}
/**
* Get Top
*
* @return double
*/
public function getTop()
{
return $this->top;
}
/**
* Set Top
*
* @param double $pValue
* @return PHPExcel_Worksheet_PageMargins
*/
public function setTop($pValue)
{
$this->top = $pValue;
return $this;
}
/**
* Get Bottom
*
* @return double
*/
public function getBottom()
{
return $this->bottom;
}
/**
* Set Bottom
*
* @param double $pValue
* @return PHPExcel_Worksheet_PageMargins
*/
public function setBottom($pValue)
{
$this->bottom = $pValue;
return $this;
}
/**
* Get Header
*
* @return double
*/
public function getHeader()
{
return $this->header;
}
/**
* Set Header
*
* @param double $pValue
* @return PHPExcel_Worksheet_PageMargins
*/
public function setHeader($pValue)
{
$this->header = $pValue;
return $this;
}
/**
* Get Footer
*
* @return double
*/
public function getFooter()
{
return $this->footer;
}
/**
* Set Footer
*
* @param double $pValue
* @return PHPExcel_Worksheet_PageMargins
*/
public function setFooter($pValue)
{
$this->footer = $pValue;
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

839
extend/PHPExcel/PHPExcel/Worksheet/PageSetup.php

@ -0,0 +1,839 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Worksheet_PageSetup
*
* <code>
* Paper size taken from Office Open XML Part 4 - Markup Language Reference, page 1988:
*
* 1 = Letter paper (8.5 in. by 11 in.)
* 2 = Letter small paper (8.5 in. by 11 in.)
* 3 = Tabloid paper (11 in. by 17 in.)
* 4 = Ledger paper (17 in. by 11 in.)
* 5 = Legal paper (8.5 in. by 14 in.)
* 6 = Statement paper (5.5 in. by 8.5 in.)
* 7 = Executive paper (7.25 in. by 10.5 in.)
* 8 = A3 paper (297 mm by 420 mm)
* 9 = A4 paper (210 mm by 297 mm)
* 10 = A4 small paper (210 mm by 297 mm)
* 11 = A5 paper (148 mm by 210 mm)
* 12 = B4 paper (250 mm by 353 mm)
* 13 = B5 paper (176 mm by 250 mm)
* 14 = Folio paper (8.5 in. by 13 in.)
* 15 = Quarto paper (215 mm by 275 mm)
* 16 = Standard paper (10 in. by 14 in.)
* 17 = Standard paper (11 in. by 17 in.)
* 18 = Note paper (8.5 in. by 11 in.)
* 19 = #9 envelope (3.875 in. by 8.875 in.)
* 20 = #10 envelope (4.125 in. by 9.5 in.)
* 21 = #11 envelope (4.5 in. by 10.375 in.)
* 22 = #12 envelope (4.75 in. by 11 in.)
* 23 = #14 envelope (5 in. by 11.5 in.)
* 24 = C paper (17 in. by 22 in.)
* 25 = D paper (22 in. by 34 in.)
* 26 = E paper (34 in. by 44 in.)
* 27 = DL envelope (110 mm by 220 mm)
* 28 = C5 envelope (162 mm by 229 mm)
* 29 = C3 envelope (324 mm by 458 mm)
* 30 = C4 envelope (229 mm by 324 mm)
* 31 = C6 envelope (114 mm by 162 mm)
* 32 = C65 envelope (114 mm by 229 mm)
* 33 = B4 envelope (250 mm by 353 mm)
* 34 = B5 envelope (176 mm by 250 mm)
* 35 = B6 envelope (176 mm by 125 mm)
* 36 = Italy envelope (110 mm by 230 mm)
* 37 = Monarch envelope (3.875 in. by 7.5 in.).
* 38 = 6 3/4 envelope (3.625 in. by 6.5 in.)
* 39 = US standard fanfold (14.875 in. by 11 in.)
* 40 = German standard fanfold (8.5 in. by 12 in.)
* 41 = German legal fanfold (8.5 in. by 13 in.)
* 42 = ISO B4 (250 mm by 353 mm)
* 43 = Japanese double postcard (200 mm by 148 mm)
* 44 = Standard paper (9 in. by 11 in.)
* 45 = Standard paper (10 in. by 11 in.)
* 46 = Standard paper (15 in. by 11 in.)
* 47 = Invite envelope (220 mm by 220 mm)
* 50 = Letter extra paper (9.275 in. by 12 in.)
* 51 = Legal extra paper (9.275 in. by 15 in.)
* 52 = Tabloid extra paper (11.69 in. by 18 in.)
* 53 = A4 extra paper (236 mm by 322 mm)
* 54 = Letter transverse paper (8.275 in. by 11 in.)
* 55 = A4 transverse paper (210 mm by 297 mm)
* 56 = Letter extra transverse paper (9.275 in. by 12 in.)
* 57 = SuperA/SuperA/A4 paper (227 mm by 356 mm)
* 58 = SuperB/SuperB/A3 paper (305 mm by 487 mm)
* 59 = Letter plus paper (8.5 in. by 12.69 in.)
* 60 = A4 plus paper (210 mm by 330 mm)
* 61 = A5 transverse paper (148 mm by 210 mm)
* 62 = JIS B5 transverse paper (182 mm by 257 mm)
* 63 = A3 extra paper (322 mm by 445 mm)
* 64 = A5 extra paper (174 mm by 235 mm)
* 65 = ISO B5 extra paper (201 mm by 276 mm)
* 66 = A2 paper (420 mm by 594 mm)
* 67 = A3 transverse paper (297 mm by 420 mm)
* 68 = A3 extra transverse paper (322 mm by 445 mm)
* </code>
*
* @category PHPExcel
* @package PHPExcel_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Worksheet_PageSetup
{
/* Paper size */
const PAPERSIZE_LETTER = 1;
const PAPERSIZE_LETTER_SMALL = 2;
const PAPERSIZE_TABLOID = 3;
const PAPERSIZE_LEDGER = 4;
const PAPERSIZE_LEGAL = 5;
const PAPERSIZE_STATEMENT = 6;
const PAPERSIZE_EXECUTIVE = 7;
const PAPERSIZE_A3 = 8;
const PAPERSIZE_A4 = 9;
const PAPERSIZE_A4_SMALL = 10;
const PAPERSIZE_A5 = 11;
const PAPERSIZE_B4 = 12;
const PAPERSIZE_B5 = 13;
const PAPERSIZE_FOLIO = 14;
const PAPERSIZE_QUARTO = 15;
const PAPERSIZE_STANDARD_1 = 16;
const PAPERSIZE_STANDARD_2 = 17;
const PAPERSIZE_NOTE = 18;
const PAPERSIZE_NO9_ENVELOPE = 19;
const PAPERSIZE_NO10_ENVELOPE = 20;
const PAPERSIZE_NO11_ENVELOPE = 21;
const PAPERSIZE_NO12_ENVELOPE = 22;
const PAPERSIZE_NO14_ENVELOPE = 23;
const PAPERSIZE_C = 24;
const PAPERSIZE_D = 25;
const PAPERSIZE_E = 26;
const PAPERSIZE_DL_ENVELOPE = 27;
const PAPERSIZE_C5_ENVELOPE = 28;
const PAPERSIZE_C3_ENVELOPE = 29;
const PAPERSIZE_C4_ENVELOPE = 30;
const PAPERSIZE_C6_ENVELOPE = 31;
const PAPERSIZE_C65_ENVELOPE = 32;
const PAPERSIZE_B4_ENVELOPE = 33;
const PAPERSIZE_B5_ENVELOPE = 34;
const PAPERSIZE_B6_ENVELOPE = 35;
const PAPERSIZE_ITALY_ENVELOPE = 36;
const PAPERSIZE_MONARCH_ENVELOPE = 37;
const PAPERSIZE_6_3_4_ENVELOPE = 38;
const PAPERSIZE_US_STANDARD_FANFOLD = 39;
const PAPERSIZE_GERMAN_STANDARD_FANFOLD = 40;
const PAPERSIZE_GERMAN_LEGAL_FANFOLD = 41;
const PAPERSIZE_ISO_B4 = 42;
const PAPERSIZE_JAPANESE_DOUBLE_POSTCARD = 43;
const PAPERSIZE_STANDARD_PAPER_1 = 44;
const PAPERSIZE_STANDARD_PAPER_2 = 45;
const PAPERSIZE_STANDARD_PAPER_3 = 46;
const PAPERSIZE_INVITE_ENVELOPE = 47;
const PAPERSIZE_LETTER_EXTRA_PAPER = 48;
const PAPERSIZE_LEGAL_EXTRA_PAPER = 49;
const PAPERSIZE_TABLOID_EXTRA_PAPER = 50;
const PAPERSIZE_A4_EXTRA_PAPER = 51;
const PAPERSIZE_LETTER_TRANSVERSE_PAPER = 52;
const PAPERSIZE_A4_TRANSVERSE_PAPER = 53;
const PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER = 54;
const PAPERSIZE_SUPERA_SUPERA_A4_PAPER = 55;
const PAPERSIZE_SUPERB_SUPERB_A3_PAPER = 56;
const PAPERSIZE_LETTER_PLUS_PAPER = 57;
const PAPERSIZE_A4_PLUS_PAPER = 58;
const PAPERSIZE_A5_TRANSVERSE_PAPER = 59;
const PAPERSIZE_JIS_B5_TRANSVERSE_PAPER = 60;
const PAPERSIZE_A3_EXTRA_PAPER = 61;
const PAPERSIZE_A5_EXTRA_PAPER = 62;
const PAPERSIZE_ISO_B5_EXTRA_PAPER = 63;
const PAPERSIZE_A2_PAPER = 64;
const PAPERSIZE_A3_TRANSVERSE_PAPER = 65;
const PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER = 66;
/* Page orientation */
const ORIENTATION_DEFAULT = 'default';
const ORIENTATION_LANDSCAPE = 'landscape';
const ORIENTATION_PORTRAIT = 'portrait';
/* Print Range Set Method */
const SETPRINTRANGE_OVERWRITE = 'O';
const SETPRINTRANGE_INSERT = 'I';
/**
* Paper size
*
* @var int
*/
private $paperSize = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER;
/**
* Orientation
*
* @var string
*/
private $orientation = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT;
/**
* Scale (Print Scale)
*
* Print scaling. Valid values range from 10 to 400
* This setting is overridden when fitToWidth and/or fitToHeight are in use
*
* @var int?
*/
private $scale = 100;
/**
* Fit To Page
* Whether scale or fitToWith / fitToHeight applies
*
* @var boolean
*/
private $fitToPage = false;
/**
* Fit To Height
* Number of vertical pages to fit on
*
* @var int?
*/
private $fitToHeight = 1;
/**
* Fit To Width
* Number of horizontal pages to fit on
*
* @var int?
*/
private $fitToWidth = 1;
/**
* Columns to repeat at left
*
* @var array Containing start column and end column, empty array if option unset
*/
private $columnsToRepeatAtLeft = array('', '');
/**
* Rows to repeat at top
*
* @var array Containing start row number and end row number, empty array if option unset
*/
private $rowsToRepeatAtTop = array(0, 0);
/**
* Center page horizontally
*
* @var boolean
*/
private $horizontalCentered = false;
/**
* Center page vertically
*
* @var boolean
*/
private $verticalCentered = false;
/**
* Print area
*
* @var string
*/
private $printArea = null;
/**
* First page number
*
* @var int
*/
private $firstPageNumber = null;
/**
* Create a new PHPExcel_Worksheet_PageSetup
*/
public function __construct()
{
}
/**
* Get Paper Size
*
* @return int
*/
public function getPaperSize()
{
return $this->paperSize;
}
/**
* Set Paper Size
*
* @param int $pValue
* @return PHPExcel_Worksheet_PageSetup
*/
public function setPaperSize($pValue = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER)
{
$this->paperSize = $pValue;
return $this;
}
/**
* Get Orientation
*
* @return string
*/
public function getOrientation()
{
return $this->orientation;
}
/**
* Set Orientation
*
* @param string $pValue
* @return PHPExcel_Worksheet_PageSetup
*/
public function setOrientation($pValue = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT)
{
$this->orientation = $pValue;
return $this;
}
/**
* Get Scale
*
* @return int?
*/
public function getScale()
{
return $this->scale;
}
/**
* Set Scale
*
* Print scaling. Valid values range from 10 to 400
* 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
* @return PHPExcel_Worksheet_PageSetup
* @throws PHPExcel_Exception
*/
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 PHPExcel_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
*
* @return int?
*/
public function getFitToHeight()
{
return $this->fitToHeight;
}
/**
* 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, $pUpdate = true)
{
$this->fitToHeight = $pValue;
if ($pUpdate) {
$this->fitToPage = true;
}
return $this;
}
/**
* Get Fit To Width
*
* @return int?
*/
public function getFitToWidth()
{
return $this->fitToWidth;
}
/**
* 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, $pUpdate = true)
{
$this->fitToWidth = $pValue;
if ($pUpdate) {
$this->fitToPage = true;
}
return $this;
}
/**
* Is Columns to repeat at left set?
*
* @return boolean
*/
public function isColumnsToRepeatAtLeftSet()
{
if (is_array($this->columnsToRepeatAtLeft)) {
if ($this->columnsToRepeatAtLeft[0] != '' && $this->columnsToRepeatAtLeft[1] != '') {
return true;
}
}
return false;
}
/**
* Get Columns to repeat at left
*
* @return array Containing start column and end column, empty array if option unset
*/
public function getColumnsToRepeatAtLeft()
{
return $this->columnsToRepeatAtLeft;
}
/**
* Set Columns to repeat at left
*
* @param array $pValue Containing start column and end column, empty array if option unset
* @return PHPExcel_Worksheet_PageSetup
*/
public function setColumnsToRepeatAtLeft($pValue = null)
{
if (is_array($pValue)) {
$this->columnsToRepeatAtLeft = $pValue;
}
return $this;
}
/**
* Set Columns to repeat at left by start and end
*
* @param string $pStart
* @param string $pEnd
* @return PHPExcel_Worksheet_PageSetup
*/
public function setColumnsToRepeatAtLeftByStartAndEnd($pStart = 'A', $pEnd = 'A')
{
$this->columnsToRepeatAtLeft = array($pStart, $pEnd);
return $this;
}
/**
* Is Rows to repeat at top set?
*
* @return boolean
*/
public function isRowsToRepeatAtTopSet()
{
if (is_array($this->rowsToRepeatAtTop)) {
if ($this->rowsToRepeatAtTop[0] != 0 && $this->rowsToRepeatAtTop[1] != 0) {
return true;
}
}
return false;
}
/**
* Get Rows to repeat at top
*
* @return array Containing start column and end column, empty array if option unset
*/
public function getRowsToRepeatAtTop()
{
return $this->rowsToRepeatAtTop;
}
/**
* Set Rows to repeat at top
*
* @param array $pValue Containing start column and end column, empty array if option unset
* @return PHPExcel_Worksheet_PageSetup
*/
public function setRowsToRepeatAtTop($pValue = null)
{
if (is_array($pValue)) {
$this->rowsToRepeatAtTop = $pValue;
}
return $this;
}
/**
* Set Rows to repeat at top by start and end
*
* @param int $pStart
* @param int $pEnd
* @return PHPExcel_Worksheet_PageSetup
*/
public function setRowsToRepeatAtTopByStartAndEnd($pStart = 1, $pEnd = 1)
{
$this->rowsToRepeatAtTop = array($pStart, $pEnd);
return $this;
}
/**
* Get center page horizontally
*
* @return bool
*/
public function getHorizontalCentered()
{
return $this->horizontalCentered;
}
/**
* Set center page horizontally
*
* @param bool $value
* @return PHPExcel_Worksheet_PageSetup
*/
public function setHorizontalCentered($value = false)
{
$this->horizontalCentered = $value;
return $this;
}
/**
* Get center page vertically
*
* @return bool
*/
public function getVerticalCentered()
{
return $this->verticalCentered;
}
/**
* Set center page vertically
*
* @param bool $value
* @return PHPExcel_Worksheet_PageSetup
*/
public function setVerticalCentered($value = false)
{
$this->verticalCentered = $value;
return $this;
}
/**
* Get print area
*
* @param int $index Identifier for a specific print area range if several ranges have been set
* Default behaviour, or a index value of 0, will return all ranges as a comma-separated string
* Otherwise, the specific range identified by the value of $index will be returned
* Print areas are numbered from 1
* @throws PHPExcel_Exception
* @return string
*/
public function getPrintArea($index = 0)
{
if ($index == 0) {
return $this->printArea;
}
$printAreas = explode(',', $this->printArea);
if (isset($printAreas[$index-1])) {
return $printAreas[$index-1];
}
throw new PHPExcel_Exception("Requested Print Area does not exist");
}
/**
* Is print area set?
*
* @param int $index Identifier for a specific print area range if several ranges have been set
* Default behaviour, or an index value of 0, will identify whether any print range is set
* Otherwise, existence of the range identified by the value of $index will be returned
* Print areas are numbered from 1
* @return boolean
*/
public function isPrintAreaSet($index = 0)
{
if ($index == 0) {
return !is_null($this->printArea);
}
$printAreas = explode(',', $this->printArea);
return isset($printAreas[$index-1]);
}
/**
* Clear a print area
*
* @param int $index Identifier for a specific print area range if several ranges have been set
* Default behaviour, or an index value of 0, will clear all print ranges that are set
* Otherwise, the range identified by the value of $index will be removed from the series
* Print areas are numbered from 1
* @return PHPExcel_Worksheet_PageSetup
*/
public function clearPrintArea($index = 0)
{
if ($index == 0) {
$this->printArea = null;
} else {
$printAreas = explode(',', $this->printArea);
if (isset($printAreas[$index-1])) {
unset($printAreas[$index-1]);
$this->printArea = implode(',', $printAreas);
}
}
return $this;
}
/**
* Set print area. e.g. 'A1:D10' or 'A1:D10,G5:M20'
*
* @param string $value
* @param int $index Identifier for a specific print area range allowing several ranges to be set
* When the method is "O"verwrite, then a positive integer index will overwrite that indexed
* entry in the print areas list; a negative index value will identify which entry to
* overwrite working bacward through the print area to the list, with the last entry as -1.
* Specifying an index value of 0, will overwrite <b>all</b> existing print ranges.
* When the method is "I"nsert, then a positive index will insert after that indexed entry in
* the print areas list, while a negative index will insert before the indexed entry.
* Specifying an index value of 0, will always append the new print range at the end of the
* list.
* Print areas are numbered from 1
* @param string $method Determines the method used when setting multiple print areas
* Default behaviour, or the "O" method, overwrites existing print area
* The "I" method, inserts the new print area before any specified index, or at the end of the list
* @return PHPExcel_Worksheet_PageSetup
* @throws PHPExcel_Exception
*/
public function setPrintArea($value, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE)
{
if (strpos($value, '!') !== false) {
throw new PHPExcel_Exception('Cell coordinate must not specify a worksheet.');
} elseif (strpos($value, ':') === false) {
throw new PHPExcel_Exception('Cell coordinate must be a range of cells.');
} elseif (strpos($value, '$') !== false) {
throw new PHPExcel_Exception('Cell coordinate must not be absolute.');
}
$value = strtoupper($value);
if ($method == self::SETPRINTRANGE_OVERWRITE) {
if ($index == 0) {
$this->printArea = $value;
} else {
$printAreas = explode(',', $this->printArea);
if ($index < 0) {
$index = count($printAreas) - abs($index) + 1;
}
if (($index <= 0) || ($index > count($printAreas))) {
throw new PHPExcel_Exception('Invalid index for setting print range.');
}
$printAreas[$index-1] = $value;
$this->printArea = implode(',', $printAreas);
}
} elseif ($method == self::SETPRINTRANGE_INSERT) {
if ($index == 0) {
$this->printArea .= ($this->printArea == '') ? $value : ','.$value;
} else {
$printAreas = explode(',', $this->printArea);
if ($index < 0) {
$index = abs($index) - 1;
}
if ($index > count($printAreas)) {
throw new PHPExcel_Exception('Invalid index for setting print range.');
}
$printAreas = array_merge(array_slice($printAreas, 0, $index), array($value), array_slice($printAreas, $index));
$this->printArea = implode(',', $printAreas);
}
} else {
throw new PHPExcel_Exception('Invalid method for setting print range.');
}
return $this;
}
/**
* Add a new print area (e.g. 'A1:D10' or 'A1:D10,G5:M20') to the list of print areas
*
* @param string $value
* @param int $index Identifier for a specific print area range allowing several ranges to be set
* A positive index will insert after that indexed entry in the print areas list, while a
* negative index will insert before the indexed entry.
* Specifying an index value of 0, will always append the new print range at the end of the
* list.
* Print areas are numbered from 1
* @return PHPExcel_Worksheet_PageSetup
* @throws PHPExcel_Exception
*/
public function addPrintArea($value, $index = -1)
{
return $this->setPrintArea($value, $index, self::SETPRINTRANGE_INSERT);
}
/**
* Set print area
*
* @param int $column1 Column 1
* @param int $row1 Row 1
* @param int $column2 Column 2
* @param int $row2 Row 2
* @param int $index Identifier for a specific print area range allowing several ranges to be set
* When the method is "O"verwrite, then a positive integer index will overwrite that indexed
* entry in the print areas list; a negative index value will identify which entry to
* overwrite working bacward through the print area to the list, with the last entry as -1.
* Specifying an index value of 0, will overwrite <b>all</b> existing print ranges.
* When the method is "I"nsert, then a positive index will insert after that indexed entry in
* the print areas list, while a negative index will insert before the indexed entry.
* Specifying an index value of 0, will always append the new print range at the end of the
* list.
* Print areas are numbered from 1
* @param string $method Determines the method used when setting multiple print areas
* Default behaviour, or the "O" method, overwrites existing print area
* The "I" method, inserts the new print area before any specified index, or at the end of the list
* @return PHPExcel_Worksheet_PageSetup
* @throws PHPExcel_Exception
*/
public function setPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE)
{
return $this->setPrintArea(
PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2,
$index,
$method
);
}
/**
* Add a new print area to the list of print areas
*
* @param int $column1 Start Column for the print area
* @param int $row1 Start Row for the print area
* @param int $column2 End Column for the print area
* @param int $row2 End Row for the print area
* @param int $index Identifier for a specific print area range allowing several ranges to be set
* A positive index will insert after that indexed entry in the print areas list, while a
* negative index will insert before the indexed entry.
* Specifying an index value of 0, will always append the new print range at the end of the
* list.
* Print areas are numbered from 1
* @return PHPExcel_Worksheet_PageSetup
* @throws PHPExcel_Exception
*/
public function addPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = -1)
{
return $this->setPrintArea(
PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2,
$index,
self::SETPRINTRANGE_INSERT
);
}
/**
* 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.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

581
extend/PHPExcel/PHPExcel/Worksheet/Protection.php

@ -0,0 +1,581 @@
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
/**
* PHPExcel_Worksheet_Protection
*
* @category PHPExcel
* @package PHPExcel_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel_Worksheet_Protection
{
/**
* Sheet
*
* @var boolean
*/
private $sheet = false;
/**
* Objects
*
* @var boolean
*/
private $objects = false;
/**
* Scenarios
*
* @var boolean
*/
private $scenarios = false;
/**
* Format cells
*
* @var boolean
*/
private $formatCells = false;
/**
* Format columns
*
* @var boolean
*/
private $formatColumns = false;
/**
* Format rows
*
* @var boolean
*/
private $formatRows = false;
/**
* Insert columns
*
* @var boolean
*/
private $insertColumns = false;
/**
* Insert rows
*
* @var boolean
*/
private $insertRows = false;
/**
* Insert hyperlinks
*
* @var boolean
*/
private $insertHyperlinks = false;
/**
* Delete columns
*
* @var boolean
*/
private $deleteColumns = false;
/**
* Delete rows
*
* @var boolean
*/
private $deleteRows = false;
/**
* Select locked cells
*
* @var boolean
*/
private $selectLockedCells = false;
/**
* Sort
*
* @var boolean
*/
private $sort = false;
/**
* AutoFilter
*
* @var boolean
*/
private $autoFilter = false;
/**
* Pivot tables
*
* @var boolean
*/
private $pivotTables = false;
/**
* Select unlocked cells
*
* @var boolean
*/
private $selectUnlockedCells = false;
/**
* Password
*
* @var string
*/
private $password = '';
/**
* Create a new PHPExcel_Worksheet_Protection
*/
public function __construct()
{
}
/**
* Is some sort of protection enabled?
*
* @return boolean
*/
public function isProtectionEnabled()
{
return $this->sheet ||
$this->objects ||
$this->scenarios ||
$this->formatCells ||
$this->formatColumns ||
$this->formatRows ||
$this->insertColumns ||
$this->insertRows ||
$this->insertHyperlinks ||
$this->deleteColumns ||
$this->deleteRows ||
$this->selectLockedCells ||
$this->sort ||
$this->autoFilter ||
$this->pivotTables ||
$this->selectUnlockedCells;
}
/**
* Get Sheet
*
* @return boolean
*/
public function getSheet()
{
return $this->sheet;
}
/**
* Set Sheet
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setSheet($pValue = false)
{
$this->sheet = $pValue;
return $this;
}
/**
* Get Objects
*
* @return boolean
*/
public function getObjects()
{
return $this->objects;
}
/**
* Set Objects
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setObjects($pValue = false)
{
$this->objects = $pValue;
return $this;
}
/**
* Get Scenarios
*
* @return boolean
*/
public function getScenarios()
{
return $this->scenarios;
}
/**
* Set Scenarios
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setScenarios($pValue = false)
{
$this->scenarios = $pValue;
return $this;
}
/**
* Get FormatCells
*
* @return boolean
*/
public function getFormatCells()
{
return $this->formatCells;
}
/**
* Set FormatCells
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setFormatCells($pValue = false)
{
$this->formatCells = $pValue;
return $this;
}
/**
* Get FormatColumns
*
* @return boolean
*/
public function getFormatColumns()
{
return $this->formatColumns;
}
/**
* Set FormatColumns
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setFormatColumns($pValue = false)
{
$this->formatColumns = $pValue;
return $this;
}
/**
* Get FormatRows
*
* @return boolean
*/
public function getFormatRows()
{
return $this->formatRows;
}
/**
* Set FormatRows
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setFormatRows($pValue = false)
{
$this->formatRows = $pValue;
return $this;
}
/**
* Get InsertColumns
*
* @return boolean
*/
public function getInsertColumns()
{
return $this->insertColumns;
}
/**
* Set InsertColumns
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setInsertColumns($pValue = false)
{
$this->insertColumns = $pValue;
return $this;
}
/**
* Get InsertRows
*
* @return boolean
*/
public function getInsertRows()
{
return $this->insertRows;
}
/**
* Set InsertRows
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setInsertRows($pValue = false)
{
$this->insertRows = $pValue;
return $this;
}
/**
* Get InsertHyperlinks
*
* @return boolean
*/
public function getInsertHyperlinks()
{
return $this->insertHyperlinks;
}
/**
* Set InsertHyperlinks
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setInsertHyperlinks($pValue = false)
{
$this->insertHyperlinks = $pValue;
return $this;
}
/**
* Get DeleteColumns
*
* @return boolean
*/
public function getDeleteColumns()
{
return $this->deleteColumns;
}
/**
* Set DeleteColumns
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setDeleteColumns($pValue = false)
{
$this->deleteColumns = $pValue;
return $this;
}
/**
* Get DeleteRows
*
* @return boolean
*/
public function getDeleteRows()
{
return $this->deleteRows;
}
/**
* Set DeleteRows
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setDeleteRows($pValue = false)
{
$this->deleteRows = $pValue;
return $this;
}
/**
* Get SelectLockedCells
*
* @return boolean
*/
public function getSelectLockedCells()
{
return $this->selectLockedCells;
}
/**
* Set SelectLockedCells
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setSelectLockedCells($pValue = false)
{
$this->selectLockedCells = $pValue;
return $this;
}
/**
* Get Sort
*
* @return boolean
*/
public function getSort()
{
return $this->sort;
}
/**
* Set Sort
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setSort($pValue = false)
{
$this->sort = $pValue;
return $this;
}
/**
* Get AutoFilter
*
* @return boolean
*/
public function getAutoFilter()
{
return $this->autoFilter;
}
/**
* Set AutoFilter
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setAutoFilter($pValue = false)
{
$this->autoFilter = $pValue;
return $this;
}
/**
* Get PivotTables
*
* @return boolean
*/
public function getPivotTables()
{
return $this->pivotTables;
}
/**
* Set PivotTables
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setPivotTables($pValue = false)
{
$this->pivotTables = $pValue;
return $this;
}
/**
* Get SelectUnlockedCells
*
* @return boolean
*/
public function getSelectUnlockedCells()
{
return $this->selectUnlockedCells;
}
/**
* Set SelectUnlockedCells
*
* @param boolean $pValue
* @return PHPExcel_Worksheet_Protection
*/
public function setSelectUnlockedCells($pValue = false)
{
$this->selectUnlockedCells = $pValue;
return $this;
}
/**
* Get Password (hashed)
*
* @return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set Password
*
* @param string $pValue
* @param boolean $pAlreadyHashed If the password has already been hashed, set this to true
* @return PHPExcel_Worksheet_Protection
*/
public function setPassword($pValue = '', $pAlreadyHashed = false)
{
if (!$pAlreadyHashed) {
$pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue);
}
$this->password = $pValue;
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}

86
extend/PHPExcel/PHPExcel/Worksheet/Row.php

@ -0,0 +1,86 @@
<?php
/**
* PHPExcel_Worksheet_Row
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_Row
{
/**
* PHPExcel_Worksheet
*
* @var PHPExcel_Worksheet
*/
private $parent;
/**
* Row index
*
* @var int
*/
private $rowIndex = 0;
/**
* Create a new row
*
* @param PHPExcel_Worksheet $parent
* @param int $rowIndex
*/
public function __construct(PHPExcel_Worksheet $parent = null, $rowIndex = 1)
{
// Set parent and row index
$this->parent = $parent;
$this->rowIndex = $rowIndex;
}
/**
* Destructor
*/
public function __destruct()
{
unset($this->parent);
}
/**
* Get row index
*
* @return int
*/
public function getRowIndex()
{
return $this->rowIndex;
}
/**
* Get cell iterator
*
* @param string $startColumn The column address at which to start iterating
* @param string $endColumn Optionally, the column address at which to stop iterating
* @return PHPExcel_Worksheet_CellIterator
*/
public function getCellIterator($startColumn = 'A', $endColumn = null)
{
return new PHPExcel_Worksheet_RowCellIterator($this->parent, $this->rowIndex, $startColumn, $endColumn);
}
}

225
extend/PHPExcel/PHPExcel/Worksheet/RowCellIterator.php

@ -0,0 +1,225 @@
<?php
/**
* PHPExcel_Worksheet_RowCellIterator
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_RowCellIterator extends PHPExcel_Worksheet_CellIterator implements Iterator
{
/**
* Row index
*
* @var int
*/
protected $rowIndex;
/**
* Start position
*
* @var int
*/
protected $startColumn = 0;
/**
* End position
*
* @var int
*/
protected $endColumn = 0;
/**
* Create a new column iterator
*
* @param PHPExcel_Worksheet $subject The worksheet to iterate over
* @param integer $rowIndex The row that we want to iterate
* @param string $startColumn The column address at which to start iterating
* @param string $endColumn Optionally, the column address at which to stop iterating
*/
public function __construct(PHPExcel_Worksheet $subject = null, $rowIndex = 1, $startColumn = 'A', $endColumn = null)
{
// Set subject and row index
$this->subject = $subject;
$this->rowIndex = $rowIndex;
$this->resetEnd($endColumn);
$this->resetStart($startColumn);
}
/**
* Destructor
*/
public function __destruct()
{
unset($this->subject);
}
/**
* (Re)Set the start column and the current column pointer
*
* @param integer $startColumn The column address at which to start iterating
* @return PHPExcel_Worksheet_RowCellIterator
* @throws PHPExcel_Exception
*/
public function resetStart($startColumn = 'A')
{
$startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumn) - 1;
$this->startColumn = $startColumnIndex;
$this->adjustForExistingOnlyRange();
$this->seek(PHPExcel_Cell::stringFromColumnIndex($this->startColumn));
return $this;
}
/**
* (Re)Set the end column
*
* @param string $endColumn The column address at which to stop iterating
* @return PHPExcel_Worksheet_RowCellIterator
* @throws PHPExcel_Exception
*/
public function resetEnd($endColumn = null)
{
$endColumn = ($endColumn) ? $endColumn : $this->subject->getHighestColumn();
$this->endColumn = PHPExcel_Cell::columnIndexFromString($endColumn) - 1;
$this->adjustForExistingOnlyRange();
return $this;
}
/**
* Set the column pointer to the selected column
*
* @param string $column The column address to set the current pointer at
* @return PHPExcel_Worksheet_RowCellIterator
* @throws PHPExcel_Exception
*/
public function seek($column = 'A')
{
$column = PHPExcel_Cell::columnIndexFromString($column) - 1;
if (($column < $this->startColumn) || ($column > $this->endColumn)) {
throw new PHPExcel_Exception("Column $column is out of range ({$this->startColumn} - {$this->endColumn})");
} elseif ($this->onlyExistingCells && !($this->subject->cellExistsByColumnAndRow($column, $this->rowIndex))) {
throw new PHPExcel_Exception('In "IterateOnlyExistingCells" mode and Cell does not exist');
}
$this->position = $column;
return $this;
}
/**
* Rewind the iterator to the starting column
*/
public function rewind()
{
$this->position = $this->startColumn;
}
/**
* Return the current cell in this worksheet row
*
* @return PHPExcel_Cell
*/
public function current()
{
return $this->subject->getCellByColumnAndRow($this->position, $this->rowIndex);
}
/**
* Return the current iterator key
*
* @return string
*/
public function key()
{
return PHPExcel_Cell::stringFromColumnIndex($this->position);
}
/**
* Set the iterator to its next value
*/
public function next()
{
do {
++$this->position;
} while (($this->onlyExistingCells) &&
(!$this->subject->cellExistsByColumnAndRow($this->position, $this->rowIndex)) &&
($this->position <= $this->endColumn));
}
/**
* Set the iterator to its previous value
*
* @throws PHPExcel_Exception
*/
public function prev()
{
if ($this->position <= $this->startColumn) {
throw new PHPExcel_Exception(
"Column is already at the beginning of range (" .
PHPExcel_Cell::stringFromColumnIndex($this->endColumn) . " - " .
PHPExcel_Cell::stringFromColumnIndex($this->endColumn) . ")"
);
}
do {
--$this->position;
} while (($this->onlyExistingCells) &&
(!$this->subject->cellExistsByColumnAndRow($this->position, $this->rowIndex)) &&
($this->position >= $this->startColumn));
}
/**
* Indicate if more columns exist in the worksheet range of columns that we're iterating
*
* @return boolean
*/
public function valid()
{
return $this->position <= $this->endColumn;
}
/**
* Validate start/end values for "IterateOnlyExistingCells" mode, and adjust if necessary
*
* @throws PHPExcel_Exception
*/
protected function adjustForExistingOnlyRange()
{
if ($this->onlyExistingCells) {
while ((!$this->subject->cellExistsByColumnAndRow($this->startColumn, $this->rowIndex)) &&
($this->startColumn <= $this->endColumn)) {
++$this->startColumn;
}
if ($this->startColumn > $this->endColumn) {
throw new PHPExcel_Exception('No cells exist within the specified range');
}
while ((!$this->subject->cellExistsByColumnAndRow($this->endColumn, $this->rowIndex)) &&
($this->endColumn >= $this->startColumn)) {
--$this->endColumn;
}
if ($this->endColumn < $this->startColumn) {
throw new PHPExcel_Exception('No cells exist within the specified range');
}
}
}
}

132
extend/PHPExcel/PHPExcel/Worksheet/RowDimension.php

@ -0,0 +1,132 @@
<?php
/**
* PHPExcel_Worksheet_RowDimension
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_RowDimension extends PHPExcel_Worksheet_Dimension
{
/**
* Row index
*
* @var int
*/
private $rowIndex;
/**
* Row height (in pt)
*
* When this is set to a negative value, the row height should be ignored by IWriter
*
* @var double
*/
private $height = -1;
/**
* ZeroHeight for Row?
*
* @var bool
*/
private $zeroHeight = false;
/**
* Create a new PHPExcel_Worksheet_RowDimension
*
* @param int $pIndex Numeric row index
*/
public function __construct($pIndex = 0)
{
// Initialise values
$this->rowIndex = $pIndex;
// set dimension as unformatted by default
parent::__construct(null);
}
/**
* Get Row Index
*
* @return int
*/
public function getRowIndex()
{
return $this->rowIndex;
}
/**
* Set Row Index
*
* @param int $pValue
* @return PHPExcel_Worksheet_RowDimension
*/
public function setRowIndex($pValue)
{
$this->rowIndex = $pValue;
return $this;
}
/**
* Get Row Height
*
* @return double
*/
public function getRowHeight()
{
return $this->height;
}
/**
* Set Row Height
*
* @param double $pValue
* @return PHPExcel_Worksheet_RowDimension
*/
public function setRowHeight($pValue = -1)
{
$this->height = $pValue;
return $this;
}
/**
* Get ZeroHeight
*
* @return bool
*/
public function getZeroHeight()
{
return $this->zeroHeight;
}
/**
* Set ZeroHeight
*
* @param bool $pValue
* @return PHPExcel_Worksheet_RowDimension
*/
public function setZeroHeight($pValue = false)
{
$this->zeroHeight = $pValue;
return $this;
}
}

192
extend/PHPExcel/PHPExcel/Worksheet/RowIterator.php

@ -0,0 +1,192 @@
<?php
/**
* PHPExcel_Worksheet_RowIterator
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_RowIterator implements Iterator
{
/**
* PHPExcel_Worksheet to iterate
*
* @var PHPExcel_Worksheet
*/
private $subject;
/**
* Current iterator position
*
* @var int
*/
private $position = 1;
/**
* Start position
*
* @var int
*/
private $startRow = 1;
/**
* End position
*
* @var int
*/
private $endRow = 1;
/**
* Create a new row iterator
*
* @param PHPExcel_Worksheet $subject The worksheet to iterate over
* @param integer $startRow The row number at which to start iterating
* @param integer $endRow Optionally, the row number at which to stop iterating
*/
public function __construct(PHPExcel_Worksheet $subject, $startRow = 1, $endRow = null)
{
// Set subject
$this->subject = $subject;
$this->resetEnd($endRow);
$this->resetStart($startRow);
}
/**
* Destructor
*/
public function __destruct()
{
unset($this->subject);
}
/**
* (Re)Set the start row and the current row pointer
*
* @param integer $startRow The row number at which to start iterating
* @return PHPExcel_Worksheet_RowIterator
* @throws PHPExcel_Exception
*/
public function resetStart($startRow = 1)
{
if ($startRow > $this->subject->getHighestRow()) {
throw new PHPExcel_Exception("Start row ({$startRow}) is beyond highest row ({$this->subject->getHighestRow()})");
}
$this->startRow = $startRow;
if ($this->endRow < $this->startRow) {
$this->endRow = $this->startRow;
}
$this->seek($startRow);
return $this;
}
/**
* (Re)Set the end row
*
* @param integer $endRow The row number at which to stop iterating
* @return PHPExcel_Worksheet_RowIterator
*/
public function resetEnd($endRow = null)
{
$this->endRow = ($endRow) ? $endRow : $this->subject->getHighestRow();
return $this;
}
/**
* Set the row pointer to the selected row
*
* @param integer $row The row number to set the current pointer at
* @return PHPExcel_Worksheet_RowIterator
* @throws PHPExcel_Exception
*/
public function seek($row = 1)
{
if (($row < $this->startRow) || ($row > $this->endRow)) {
throw new PHPExcel_Exception("Row $row is out of range ({$this->startRow} - {$this->endRow})");
}
$this->position = $row;
return $this;
}
/**
* Rewind the iterator to the starting row
*/
public function rewind()
{
$this->position = $this->startRow;
}
/**
* Return the current row in this worksheet
*
* @return PHPExcel_Worksheet_Row
*/
public function current()
{
return new PHPExcel_Worksheet_Row($this->subject, $this->position);
}
/**
* Return the current iterator key
*
* @return int
*/
public function key()
{
return $this->position;
}
/**
* Set the iterator to its next value
*/
public function next()
{
++$this->position;
}
/**
* Set the iterator to its previous value
*/
public function prev()
{
if ($this->position <= $this->startRow) {
throw new PHPExcel_Exception("Row is already at the beginning of range ({$this->startRow} - {$this->endRow})");
}
--$this->position;
}
/**
* Indicate if more rows exist in the worksheet range of rows that we're iterating
*
* @return boolean
*/
public function valid()
{
return $this->position <= $this->endRow;
}
}

187
extend/PHPExcel/PHPExcel/Worksheet/SheetView.php

@ -0,0 +1,187 @@
<?php
/**
* PHPExcel_Worksheet_SheetView
*
* Copyright (c) 2006 - 2015 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_Worksheet
* @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version ##VERSION##, ##DATE##
*/
class PHPExcel_Worksheet_SheetView
{
/* Sheet View types */
const SHEETVIEW_NORMAL = 'normal';
const SHEETVIEW_PAGE_LAYOUT = 'pageLayout';
const SHEETVIEW_PAGE_BREAK_PREVIEW = 'pageBreakPreview';
private static $sheetViewTypes = array(
self::SHEETVIEW_NORMAL,
self::SHEETVIEW_PAGE_LAYOUT,
self::SHEETVIEW_PAGE_BREAK_PREVIEW,
);
/**
* ZoomScale
*
* Valid values range from 10 to 400.
*
* @var int
*/
private $zoomScale = 100;
/**
* ZoomScaleNormal
*
* Valid values range from 10 to 400.
*
* @var int
*/
private $zoomScaleNormal = 100;
/**
* View
*
* Valid values range from 10 to 400.
*
* @var string
*/
private $sheetviewType = self::SHEETVIEW_NORMAL;
/**
* Create a new PHPExcel_Worksheet_SheetView
*/
public function __construct()
{
}
/**
* Get ZoomScale
*
* @return int
*/
public function getZoomScale()
{
return $this->zoomScale;
}
/**
* Set ZoomScale
*
* Valid values range from 10 to 400.
*
* @param int $pValue
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_SheetView
*/
public function setZoomScale($pValue = 100)
{
// 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 >= 1
if (($pValue >= 1) || is_null($pValue)) {
$this->zoomScale = $pValue;
} else {
throw new PHPExcel_Exception("Scale must be greater than or equal to 1.");
}
return $this;
}
/**
* Get ZoomScaleNormal
*
* @return int
*/
public function getZoomScaleNormal()
{
return $this->zoomScaleNormal;
}
/**
* Set ZoomScale
*
* Valid values range from 10 to 400.
*
* @param int $pValue
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_SheetView
*/
public function setZoomScaleNormal($pValue = 100)
{
if (($pValue >= 1) || is_null($pValue)) {
$this->zoomScaleNormal = $pValue;
} else {
throw new PHPExcel_Exception("Scale must be greater than or equal to 1.");
}
return $this;
}
/**
* Get View
*
* @return string
*/
public function getView()
{
return $this->sheetviewType;
}
/**
* Set View
*
* Valid values are
* 'normal' self::SHEETVIEW_NORMAL
* 'pageLayout' self::SHEETVIEW_PAGE_LAYOUT
* 'pageBreakPreview' self::SHEETVIEW_PAGE_BREAK_PREVIEW
*
* @param string $pValue
* @throws PHPExcel_Exception
* @return PHPExcel_Worksheet_SheetView
*/
public function setView($pValue = null)
{
// MS Excel 2007 allows setting the view to 'normal', 'pageLayout' or 'pageBreakPreview' via the user interface
if ($pValue === null) {
$pValue = self::SHEETVIEW_NORMAL;
}
if (in_array($pValue, self::$sheetViewTypes)) {
$this->sheetviewType = $pValue;
} else {
throw new PHPExcel_Exception("Invalid sheetview layout type.");
}
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone()
{
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
Loading…
Cancel
Save