93 changed files with 40125 additions and 0 deletions
@ -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)); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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'); |
||||
|
} |
||||
|
} |
||||
@ -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'); |
||||
|
} |
||||
|
} |
||||
@ -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'); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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)); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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 = ''); |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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()); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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. |
||||
|
|
||||
@ -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() |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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()"); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
*/ |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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 ) |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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! |
||||
|
|
||||
|
|
||||
File diff suppressed because it is too large
@ -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 |
||||
@ -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))); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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…
Reference in new issue