Migration from off-site Subversion repository (part 1).
git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@59884 2327b42d-5241-43d6-9e2a-de5ac946f064
This commit is contained in:
commit
509f27e5c6
|
@ -0,0 +1,2 @@
|
||||||
|
@ECHO OFF
|
||||||
|
phing -f build.xml release-documentation
|
|
@ -0,0 +1,2 @@
|
||||||
|
@ECHO OFF
|
||||||
|
phing -f build.xml release-pear
|
|
@ -0,0 +1,2 @@
|
||||||
|
@ECHO OFF
|
||||||
|
phing -f build.xml release-standard
|
|
@ -0,0 +1,216 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<project name="PHPExcel" default="release-standard" basedir=".">
|
||||||
|
<taskdef classname="phing.tasks.ext.d51PearPkg2Task" name="d51pearpkg2"/>
|
||||||
|
|
||||||
|
<propertyprompt propertyName="packageVersion" defaultValue="1.0.0"
|
||||||
|
promptText="Enter PHPExcel version number" />
|
||||||
|
<propertyprompt propertyName="releaseDate" defaultValue="2010-01-01"
|
||||||
|
promptText="Enter PHPExcel release date" />
|
||||||
|
|
||||||
|
<adhoc-task name="phpzip">
|
||||||
|
<![CDATA[
|
||||||
|
class PhpZipTask extends Task {
|
||||||
|
private $destinationFile;
|
||||||
|
private $filesets = array();
|
||||||
|
|
||||||
|
function setDestfile(PhingFile $f) {
|
||||||
|
$this->destinationFile = $f;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFileSet() {
|
||||||
|
$num = array_push($this->filesets, new FileSet());
|
||||||
|
return $this->filesets[$num-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
if ($this->destinationFile === null || empty($this->filesets)) {
|
||||||
|
throw new BuildException("You must specify a file or fileset(s) for the <phpzip> task.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// compile a list of all files to add to the file, both file attrib and fileset elements
|
||||||
|
// can be used.
|
||||||
|
$files = array();
|
||||||
|
if (!empty($this->filesets)) {
|
||||||
|
$filenames = array();
|
||||||
|
foreach($this->filesets as $fs) {
|
||||||
|
try {
|
||||||
|
$ds = $fs->getDirectoryScanner($this->project);
|
||||||
|
$filenames = $ds->getIncludedFiles(); // get included filenames
|
||||||
|
$dir = $fs->getDir($this->project);
|
||||||
|
foreach ($filenames as $fname) {
|
||||||
|
$files[] = new PhingFile($dir, $fname);
|
||||||
|
}
|
||||||
|
} catch (BuildException $be) {
|
||||||
|
$this->log($be->getMessage(), Project::MSG_WARN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$objZip = new ZipArchive();
|
||||||
|
if ($objZip->open($this->destinationFile, ZIPARCHIVE::OVERWRITE) !== true) {
|
||||||
|
throw new Exeption("Could not open " . $strResultingFile . " for writing!");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->log("Creating ZIP archive of " . count($files) . " files...");
|
||||||
|
|
||||||
|
foreach($files as $file) {
|
||||||
|
$this->log("Processing file " . $this->_cleanFileName($file) . " ...");
|
||||||
|
$contents = file_get_contents($file);
|
||||||
|
$objZip->addFromString( $this->_cleanFileName($file), $contents );
|
||||||
|
}
|
||||||
|
|
||||||
|
$objZip->close();
|
||||||
|
|
||||||
|
$this->log("Created ZIP archive " . $this->destinationFile . '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup a filename
|
||||||
|
*
|
||||||
|
* @param string $strFile Filename
|
||||||
|
* @return string Filename
|
||||||
|
*/
|
||||||
|
protected function _cleanFileName($strFile) {
|
||||||
|
$strFile = str_replace('../', '', $strFile);
|
||||||
|
$strFile = str_replace('.\\build\\', '', $strFile);
|
||||||
|
$strFile = str_replace('WINDOWS', '', $strFile);
|
||||||
|
|
||||||
|
while (preg_match('/\/\//i', $strFile)) {
|
||||||
|
$strFile = str_replace('//', '/', $strFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $strFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]>
|
||||||
|
</adhoc-task>
|
||||||
|
|
||||||
|
<target name="prepare">
|
||||||
|
<echo msg="Creating build directory: ./build" />
|
||||||
|
<mkdir dir="./build" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="build" depends="prepare">
|
||||||
|
<echo msg="Copying source files to build directory..." />
|
||||||
|
|
||||||
|
<copy todir="./build/Classes" overwrite="true">
|
||||||
|
<fileset dir="../Classes">
|
||||||
|
<include name="**/*" />
|
||||||
|
<exclude name="**/.svn" />
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
|
||||||
|
<copy todir="./build/Documentation" overwrite="true">
|
||||||
|
<fileset dir="../Documentation">
|
||||||
|
<include name="*.*" />
|
||||||
|
<exclude name="**/.svn" />
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
<mkdir dir="./build/Documentation/API" />
|
||||||
|
|
||||||
|
<copy todir="./build/Tests" overwrite="true">
|
||||||
|
<fileset dir="../Tests">
|
||||||
|
<include name="**/*" />
|
||||||
|
<exclude name="**/.svn" />
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
|
||||||
|
<copy file="../changelog.txt" tofile="./build/changelog.txt" overwrite="true" />
|
||||||
|
<copy file="../license.txt" tofile="./build/license.txt" overwrite="true" />
|
||||||
|
<copy file="../install.txt" tofile="./build/install.txt" overwrite="true" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="versionNumber" depends="build">
|
||||||
|
<reflexive>
|
||||||
|
<fileset dir="./build">
|
||||||
|
<include pattern="**/*" />
|
||||||
|
</fileset>
|
||||||
|
<filterchain>
|
||||||
|
<replaceregexp>
|
||||||
|
<regexp pattern="##VERSION##" replace="${packageVersion}"/>
|
||||||
|
<regexp pattern="##DATE##" replace="${releaseDate}"/>
|
||||||
|
</replaceregexp>
|
||||||
|
</filterchain>
|
||||||
|
</reflexive>
|
||||||
|
|
||||||
|
<reflexive>
|
||||||
|
<fileset dir="./build">
|
||||||
|
<include pattern="**/changelog.txt" />
|
||||||
|
</fileset>
|
||||||
|
<filterchain>
|
||||||
|
<replaceregexp>
|
||||||
|
<regexp pattern="Fixed in SVN" replace="${releaseDate} (v${packageVersion})"/>
|
||||||
|
</replaceregexp>
|
||||||
|
</filterchain>
|
||||||
|
</reflexive>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="apidocs" depends="versionNumber">
|
||||||
|
<echo msg="Generating API documentation..." />
|
||||||
|
<phpdoc title="PHPExcel classes"
|
||||||
|
destdir="./build/Documentation/API"
|
||||||
|
sourcecode="true"
|
||||||
|
output="HTML:Smarty:PHP"
|
||||||
|
defaultcategoryname="PHPExcel"
|
||||||
|
defaultpackagename="PHPExcel"
|
||||||
|
pear="true">
|
||||||
|
<fileset dir="./build/Classes">
|
||||||
|
<include name="**/*.php" />
|
||||||
|
</fileset>
|
||||||
|
</phpdoc>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="release-standard" depends="apidocs">
|
||||||
|
<mkdir dir="./release" />
|
||||||
|
|
||||||
|
<echo msg="Creating release package (v${packageVersion})..." />
|
||||||
|
<phpzip destfile="./release/${packageVersion}.zip">
|
||||||
|
<fileset dir="./build">
|
||||||
|
<include name="**/*" />
|
||||||
|
</fileset>
|
||||||
|
</phpzip>
|
||||||
|
|
||||||
|
<echo msg="Cleaning build directory: ./build" />
|
||||||
|
<delete dir="./build" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="release-pear" depends="versionNumber">
|
||||||
|
<mkdir dir="./release" />
|
||||||
|
|
||||||
|
<echo msg="Creating PEAR release package (v${packageVersion})..." />
|
||||||
|
|
||||||
|
<d51pearpkg2 dir="./build/Classes" baseinstalldir="PHPExcel">
|
||||||
|
<name>PHPExcel</name>
|
||||||
|
<summary>PHP Excel classes</summary>
|
||||||
|
<channel>pear.pearplex.net</channel>
|
||||||
|
<description>Project providing a set of classes for the PHP programming language, which allow you to write to Excel 2007 files and read from Excel 2007 files.</description>
|
||||||
|
<notes>This package ONLY contains the class files, not the documentation and example code. Please refer to http://www.codeplex.com/PHPExcel for those files.</notes>
|
||||||
|
<lead user="maartenba" name="Maarten Balliauw" email="maarten@phpexcel.net"/>
|
||||||
|
<license uri="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt">LGPL</license>
|
||||||
|
<version release="${packageVersion}" api="${packageVersion}"/>
|
||||||
|
<stability release="stable" api="stable"/>
|
||||||
|
<dependencies>
|
||||||
|
<php minimum_version="5.2.0"/>
|
||||||
|
<pear minimum_version="1.4.0"/>
|
||||||
|
<extension name="zip" minimum_version="1.8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
</d51pearpkg2>
|
||||||
|
|
||||||
|
<exec command="pear package ./build/Classes/package.xml"/>
|
||||||
|
<move file="PHPExcel-${packageVersion}.tgz" tofile="release/PHPExcel-${packageVersion}.tgz" overwrite="true"/>
|
||||||
|
|
||||||
|
<echo msg="Cleaning build directory: ./build" />
|
||||||
|
<delete dir="./build" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="release-documentation">
|
||||||
|
<mkdir dir="./release" />
|
||||||
|
|
||||||
|
<echo msg="Creating documentation release (v${packageVersion})..." />
|
||||||
|
<copy todir="./release" overwrite="true">
|
||||||
|
<fileset dir="../Documentation">
|
||||||
|
<include name="*.doc" />
|
||||||
|
</fileset>
|
||||||
|
</copy>
|
||||||
|
</target>
|
||||||
|
</project>
|
|
@ -0,0 +1,4 @@
|
||||||
|
@set PHPINSTALLDIR=C:\php\5.2.9\;C:\php5;C:\LAMP\php;C:\LAMP\php5;D:\LAMP\php5
|
||||||
|
@set PATH=%PHPINSTALLDIR%;%PATH%;
|
||||||
|
cls
|
||||||
|
php build.php
|
|
@ -0,0 +1,336 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file creates a build of PHPExcel
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Build parameters
|
||||||
|
$sVersion = "";
|
||||||
|
$sDate = "";
|
||||||
|
|
||||||
|
// Read build parameters from STDIN
|
||||||
|
$stdin = fopen("php://stdin", 'r');
|
||||||
|
echo "PHPExcel build script\n";
|
||||||
|
echo "---------------------\n";
|
||||||
|
echo "Enter the version number you want to add to the build:\t\t\t";
|
||||||
|
$sVersion = rtrim(fread($stdin, 1024));
|
||||||
|
|
||||||
|
echo "Enter the date number you want to add to the build: (YYYY-MM-DD)\t";
|
||||||
|
$sDate = rtrim(fread($stdin, 1024));
|
||||||
|
|
||||||
|
echo "\n\n";
|
||||||
|
|
||||||
|
// Specify paths and files to include
|
||||||
|
$aFilesToInclude = array('../changelog.txt', '../install.txt', '../license.txt');
|
||||||
|
$aPathsToInclude = array('../Classes', '../Tests', '../Documentation');
|
||||||
|
$aIgnorePatterns = array('/\.svn/i', '/\.settings/i', '/\.project/i', '/\.projectOptions/i', '/\.cache/i', '/assets/i');
|
||||||
|
$sClassPath = '../Classes';
|
||||||
|
$sPEARPath = 'C:\php\5.2.9\pear';
|
||||||
|
$sAPIDocumentation = '../Documentation/API/';
|
||||||
|
|
||||||
|
// Create API documentation folder and tell to create documentation
|
||||||
|
@mkdir($sAPIDocumentation);
|
||||||
|
echo "Please, generate API documentation using phpDocumentor.\r\n";
|
||||||
|
|
||||||
|
$finished = '';
|
||||||
|
while (strtolower($finished) != 'y') {
|
||||||
|
$finished = '';
|
||||||
|
echo "Has documentation generation finished? (y/n)\t";
|
||||||
|
$finished = rtrim(fread($stdin, 1024));
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n\n\n";
|
||||||
|
|
||||||
|
// Resulting file
|
||||||
|
$strResultingFile = $sVersion . '.zip';
|
||||||
|
|
||||||
|
// Starting build
|
||||||
|
echo date('H:i:s') . " Starting build...\n";
|
||||||
|
|
||||||
|
// Create new ZIP file and open it for writing
|
||||||
|
echo date('H:i:s') . " Creating ZIP archive...\n";
|
||||||
|
$objZip = new ZipArchive();
|
||||||
|
|
||||||
|
// Try opening the ZIP file
|
||||||
|
if ($objZip->open($strResultingFile, ZIPARCHIVE::OVERWRITE) !== true) {
|
||||||
|
throw new Exeption("Could not open " . $strResultingFile . " for writing!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add files to include
|
||||||
|
foreach ($aFilesToInclude as $strFile) {
|
||||||
|
echo date('H:i:s') . " Adding file $strFile\n";
|
||||||
|
addFileToZIP($strFile, $objZip, $sVersion, $sDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add paths to include
|
||||||
|
foreach ($aPathsToInclude as $strPath) {
|
||||||
|
addPathToZIP($strPath, $objZip, $sVersion, $sDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set archive comment...
|
||||||
|
echo date('H:i:s') . " Set archive comment...\n";
|
||||||
|
$objZip->setArchiveComment('PHPExcel - http://www.codeplex.com/PHPExcel');
|
||||||
|
|
||||||
|
// Close file
|
||||||
|
echo date('H:i:s') . " Saving ZIP archive...\n";
|
||||||
|
$objZip->close();
|
||||||
|
|
||||||
|
// Copy classes directory
|
||||||
|
echo date('H:i:s') . " Copying class directory...\n";
|
||||||
|
mkdir('./tmp');
|
||||||
|
dircopy($sClassPath, './tmp');
|
||||||
|
|
||||||
|
// Create PEAR package.xml
|
||||||
|
echo date('H:i:s') . " Creating PEAR package.xml...\n";
|
||||||
|
$packageFile = file_get_contents('package.xml');
|
||||||
|
$packageFile = replaceMetaData($packageFile, $sVersion, $sDate);
|
||||||
|
|
||||||
|
$packageFile = str_replace('##PEAR_DIR##', addPathToPEAR('./tmp', '', $sVersion, $sDate), $packageFile);
|
||||||
|
$fh = fopen('./tmp/package.xml', 'w');
|
||||||
|
fwrite($fh, $packageFile);
|
||||||
|
fclose($fh);
|
||||||
|
|
||||||
|
// Create PEAR package
|
||||||
|
echo date('H:i:s') . " Creating PEAR package...\n";
|
||||||
|
echo shell_exec("$sPEARPath package ./tmp/package.xml");
|
||||||
|
|
||||||
|
// Wait a minute (TortoiseSVN on USB stick is slow!)
|
||||||
|
echo date('H:i:s') . " Waiting...\n";
|
||||||
|
sleep(120);
|
||||||
|
|
||||||
|
// Clean temporary files
|
||||||
|
echo date('H:i:s') . " Cleaning temporary files...\n";
|
||||||
|
unlink('./tmp/package.xml');
|
||||||
|
rm('./tmp');
|
||||||
|
|
||||||
|
// Finished build
|
||||||
|
echo date('H:i:s') . " Finished build!\n";
|
||||||
|
fclose($stdin);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a specific path's files and folders to a ZIP object
|
||||||
|
*
|
||||||
|
* @param string $strPath Path to add
|
||||||
|
* @param ZipArchive $objZip ZipArchive object
|
||||||
|
* @param string $strVersion Version string
|
||||||
|
* @param string $strDate Date string
|
||||||
|
*/
|
||||||
|
function addPathToZIP($strPath, $objZip, $strVersion, $strDate) {
|
||||||
|
global $aIgnorePatterns;
|
||||||
|
|
||||||
|
echo date('H:i:s') . " Adding path $strPath...\n";
|
||||||
|
|
||||||
|
$currentDir = opendir($strPath);
|
||||||
|
while ($strFile = readdir($currentDir)) {
|
||||||
|
if ($strFile != '.' && $strFile != '..') {
|
||||||
|
if (is_file($strPath . '/' . $strFile)) {
|
||||||
|
addFileToZIP($strPath . '/' . $strFile, $objZip, $strVersion, $strDate);
|
||||||
|
} else if (is_dir($strPath . '/' . $strFile)) {
|
||||||
|
if (!shouldIgnore($strFile)) {
|
||||||
|
addPathToZIP( ($strPath . '/' . $strFile), $objZip, $strVersion, $strDate );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a specific file to ZIP
|
||||||
|
*
|
||||||
|
* @param string $strFile File to add
|
||||||
|
* @param ZipArchive $objZip ZipArchive object
|
||||||
|
* @param string $strVersion Version string
|
||||||
|
* @param string $strDate Date string
|
||||||
|
*/
|
||||||
|
function addFileToZIP($strFile, $objZip, $strVersion, $strDate) {
|
||||||
|
if (!shouldIgnore($strFile)) {
|
||||||
|
$fileContents = file_get_contents($strFile);
|
||||||
|
$fileContents = replaceMetaData($fileContents, $strVersion, $strDate);
|
||||||
|
|
||||||
|
//$objZip->addFile($strFile, cleanFileName($strFile));
|
||||||
|
$objZip->addFromString( cleanFileName($strFile), $fileContents );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup a filename
|
||||||
|
*
|
||||||
|
* @param string $strFile Filename
|
||||||
|
* @return string Filename
|
||||||
|
*/
|
||||||
|
function cleanFileName($strFile) {
|
||||||
|
$strFile = str_replace('../', '', $strFile);
|
||||||
|
$strFile = str_replace('WINDOWS', '', $strFile);
|
||||||
|
|
||||||
|
while (preg_match('/\/\//i', $strFile)) {
|
||||||
|
$strFile = str_replace('//', '/', $strFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $strFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace metadata in string
|
||||||
|
*
|
||||||
|
* @param string $strString String contents
|
||||||
|
* @param string $strVersion Version string
|
||||||
|
* @param string $strDate Date string
|
||||||
|
* @return string String contents
|
||||||
|
*/
|
||||||
|
function replaceMetaData($strString, $strVersion, $strDate) {
|
||||||
|
$strString = str_replace('##VERSION##', $strVersion, $strString);
|
||||||
|
$strString = str_replace('##DATE##', $strDate, $strString);
|
||||||
|
return $strString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a specific path's files and folders to a PEAR dir list
|
||||||
|
*
|
||||||
|
* @param string $strPath Path to add
|
||||||
|
* @param string $strPEAR String containing PEAR dir definitions
|
||||||
|
* @param string $strVersion Version string
|
||||||
|
* @param string $strDate Date string
|
||||||
|
* @return string String containing PEAR dir definitions
|
||||||
|
*/
|
||||||
|
function addPathToPEAR($strPath, $strPEAR, $strVersion, $strDate) {
|
||||||
|
global $aIgnorePatterns;
|
||||||
|
|
||||||
|
$currentDir = opendir($strPath);
|
||||||
|
while ($strFile = readdir($currentDir)) {
|
||||||
|
if ($strFile != '.' && $strFile != '..') {
|
||||||
|
if (is_file($strPath . '/' . $strFile) && !preg_match('/package.xml/i', $strFile)) {
|
||||||
|
$strPEAR .= addFileToPEAR($strPath . '/' . $strFile, '', $strVersion, $strDate);
|
||||||
|
} else if (is_dir($strPath . '/' . $strFile)) {
|
||||||
|
if (!shouldIgnore($strFile)) {
|
||||||
|
$strPEAR .= '<dir name="' . $strFile . '">';
|
||||||
|
$strPEAR .= addPathToPEAR( ($strPath . '/' . $strFile), '', $strVersion, $strDate );
|
||||||
|
$strPEAR .= '</dir>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $strPEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a specific file to a PEAR dir list
|
||||||
|
*
|
||||||
|
* @param string $strFile File to add
|
||||||
|
* @param string $strPEAR String containing PEAR dir definitions
|
||||||
|
* @param string $strVersion Version string
|
||||||
|
* @param string $strDate Date string
|
||||||
|
* @return string String containing PEAR dir definitions
|
||||||
|
*/
|
||||||
|
function addFileToPEAR($strFile, $strPEAR, $strVersion, $strDate) {
|
||||||
|
if (!shouldIgnore($strFile)) {
|
||||||
|
$fileContents = file_get_contents($strFile);
|
||||||
|
$fileContents = replaceMetaData($fileContents, $strVersion, $strDate);
|
||||||
|
$fh = fopen($strFile, 'w');
|
||||||
|
fwrite($fh, $fileContents);
|
||||||
|
fclose($fh);
|
||||||
|
|
||||||
|
$strPEAR .= '<file name="' . basename($strFile) . '" role="php" />';
|
||||||
|
|
||||||
|
return $strPEAR;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a complete directory
|
||||||
|
*
|
||||||
|
* @param string $srcdir Source directory
|
||||||
|
* @param string $dstdir Destination directory
|
||||||
|
* @return int Number of copied files
|
||||||
|
*/
|
||||||
|
function dircopy($srcdir, $dstdir, $verbose = false) {
|
||||||
|
$num = 0;
|
||||||
|
if(!is_dir($dstdir) && !shouldIgnore($dstdir)) mkdir($dstdir);
|
||||||
|
if($curdir = opendir($srcdir)) {
|
||||||
|
while($file = readdir($curdir)) {
|
||||||
|
if($file != '.' && $file != '..') {
|
||||||
|
$srcfile = $srcdir . '\\' . $file;
|
||||||
|
$dstfile = $dstdir . '\\' . $file;
|
||||||
|
if(is_file($srcfile) && !shouldIgnore($srcfile)) {
|
||||||
|
if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1;
|
||||||
|
if($ow > 0) {
|
||||||
|
if($verbose) echo "Copying '$srcfile' to '$dstfile'...";
|
||||||
|
if(copy($srcfile, $dstfile)) {
|
||||||
|
touch($dstfile, filemtime($srcfile)); $num++;
|
||||||
|
if($verbose) echo "OK\n";
|
||||||
|
}
|
||||||
|
else echo "Error: File '$srcfile' could not be copied!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(is_dir($srcfile) && !shouldIgnore($srcfile)) {
|
||||||
|
$num += dircopy($srcfile, $dstfile, $verbose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir($curdir);
|
||||||
|
}
|
||||||
|
return $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rm() -- Very Vigorously erase files and directories. Also hidden files !!!!
|
||||||
|
*
|
||||||
|
* @param $dir string
|
||||||
|
* be carefull to:
|
||||||
|
* if($obj=='.' || $obj=='..') continue;
|
||||||
|
* if not it will erase all the server...it happened to me ;)
|
||||||
|
* the function is permission dependent.
|
||||||
|
*/
|
||||||
|
function rm($dir) {
|
||||||
|
if(!$dh = @opendir($dir)) return;
|
||||||
|
while (($obj = readdir($dh))) {
|
||||||
|
if($obj=='.' || $obj=='..') continue;
|
||||||
|
@chmod($dir.'/'.$obj, 0777);
|
||||||
|
if (!@unlink($dir.'/'.$obj)) rm($dir.'/'.$obj);
|
||||||
|
}
|
||||||
|
@rmdir($dir);
|
||||||
|
@shell_exec('rmdir /S /Q "' . $dir . '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should a file/folder be ignored?
|
||||||
|
*
|
||||||
|
* @param string $pName
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function shouldIgnore($pName = '') {
|
||||||
|
global $aIgnorePatterns;
|
||||||
|
|
||||||
|
$ignore = false;
|
||||||
|
foreach ($aIgnorePatterns as $ignorePattern) {
|
||||||
|
if (preg_match($ignorePattern, $pName)) {
|
||||||
|
$ignore = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ignore;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
|
||||||
|
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
|
||||||
|
http://pear.php.net/dtd/tasks-1.0.xsd
|
||||||
|
http://pear.php.net/dtd/package-2.0
|
||||||
|
http://pear.php.net/dtd/package-2.0.xsd">
|
||||||
|
<name>PHPExcel</name>
|
||||||
|
<uri>http://www.codeplex.com/PHPExcel/PHPExcel-##VERSION##</uri>
|
||||||
|
<summary>PHP Excel classes</summary>
|
||||||
|
<description>
|
||||||
|
Project providing a set of classes for the PHP programming language, which allow you to write to Excel 2007 files and read from Excel 2007 files.
|
||||||
|
</description>
|
||||||
|
<lead>
|
||||||
|
<name>Maarten Balliauw</name>
|
||||||
|
<user>maartenba</user>
|
||||||
|
<email>maarten@phpexcel.net</email>
|
||||||
|
<active>yes</active>
|
||||||
|
</lead>
|
||||||
|
<date>##DATE##</date>
|
||||||
|
<version>
|
||||||
|
<release>##VERSION##</release>
|
||||||
|
<api>##VERSION##</api>
|
||||||
|
</version>
|
||||||
|
<stability>
|
||||||
|
<release>stable</release>
|
||||||
|
<api>stable</api>
|
||||||
|
</stability>
|
||||||
|
<license uri="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt">LGPL</license>
|
||||||
|
<notes>This package ONLY contains the class files, not the documentation and example code. Please refer to http://www.codeplex.com/PHPExcel for those files.</notes>
|
||||||
|
<contents>
|
||||||
|
<dir name="/">
|
||||||
|
##PEAR_DIR##
|
||||||
|
</dir>
|
||||||
|
</contents>
|
||||||
|
<dependencies>
|
||||||
|
<required>
|
||||||
|
<php>
|
||||||
|
<min>5.0</min>
|
||||||
|
</php>
|
||||||
|
<pearinstaller>
|
||||||
|
<min>1.4.0</min>
|
||||||
|
</pearinstaller>
|
||||||
|
<extension>
|
||||||
|
<name>zip</name>
|
||||||
|
</extension>
|
||||||
|
</required>
|
||||||
|
</dependencies>
|
||||||
|
<phprelease>
|
||||||
|
<filelist>
|
||||||
|
</filelist>
|
||||||
|
</phprelease>
|
||||||
|
</package>
|
|
@ -0,0 +1,802 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 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 */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Document properties
|
||||||
|
*
|
||||||
|
* @var PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
private $_properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Document security
|
||||||
|
*
|
||||||
|
* @var PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
private $_security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of Worksheet objects
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Worksheet[]
|
||||||
|
*/
|
||||||
|
private $_workSheetCollection = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active sheet index
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_activeSheetIndex = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Named ranges
|
||||||
|
*
|
||||||
|
* @var PHPExcel_NamedRange[]
|
||||||
|
*/
|
||||||
|
private $_namedRanges = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CellXf supervisor
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Style
|
||||||
|
*/
|
||||||
|
private $_cellXfSupervisor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CellXf collection
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Style[]
|
||||||
|
*/
|
||||||
|
private $_cellXfCollection = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CellStyleXf collection
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Style[]
|
||||||
|
*/
|
||||||
|
private $_cellStyleXfCollection = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel with one Worksheet
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Initialise worksheet collection and add one worksheet
|
||||||
|
$this->_workSheetCollection = array();
|
||||||
|
$this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
|
||||||
|
$this->_activeSheetIndex = 0;
|
||||||
|
|
||||||
|
// Create document properties
|
||||||
|
$this->_properties = new PHPExcel_DocumentProperties();
|
||||||
|
|
||||||
|
// Create document security
|
||||||
|
$this->_security = new PHPExcel_DocumentSecurity();
|
||||||
|
|
||||||
|
// Set named ranges
|
||||||
|
$this->_namedRanges = array();
|
||||||
|
|
||||||
|
// Create the cellXf supervisor
|
||||||
|
$this->_cellXfSupervisor = new PHPExcel_Style(true);
|
||||||
|
$this->_cellXfSupervisor->bindParent($this);
|
||||||
|
|
||||||
|
// Create the default style
|
||||||
|
$this->addCellXf(new PHPExcel_Style);
|
||||||
|
$this->addCellStyleXf(new PHPExcel_Style);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function disconnectWorksheets() {
|
||||||
|
foreach($this->_workSheetCollection as $k => &$worksheet) {
|
||||||
|
$worksheet->disconnectCells();
|
||||||
|
$this->_workSheetCollection[$k] = null;
|
||||||
|
}
|
||||||
|
unset($worksheet);
|
||||||
|
$this->_workSheetCollection = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get properties
|
||||||
|
*
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function getProperties()
|
||||||
|
{
|
||||||
|
return $this->_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set properties
|
||||||
|
*
|
||||||
|
* @param PHPExcel_DocumentProperties $pValue
|
||||||
|
*/
|
||||||
|
public function setProperties(PHPExcel_DocumentProperties $pValue)
|
||||||
|
{
|
||||||
|
$this->_properties = $pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get security
|
||||||
|
*
|
||||||
|
* @return PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
public function getSecurity()
|
||||||
|
{
|
||||||
|
return $this->_security;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set security
|
||||||
|
*
|
||||||
|
* @param PHPExcel_DocumentSecurity $pValue
|
||||||
|
*/
|
||||||
|
public function setSecurity(PHPExcel_DocumentSecurity $pValue)
|
||||||
|
{
|
||||||
|
$this->_security = $pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active sheet
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
public function getActiveSheet()
|
||||||
|
{
|
||||||
|
return $this->_workSheetCollection[$this->_activeSheetIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create sheet and add it to this workbook
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
public function createSheet($iSheetIndex = null)
|
||||||
|
{
|
||||||
|
$newSheet = new PHPExcel_Worksheet($this);
|
||||||
|
$this->addSheet($newSheet, $iSheetIndex);
|
||||||
|
return $newSheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add sheet
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Worksheet $pSheet
|
||||||
|
* @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addSheet(PHPExcel_Worksheet $pSheet = null, $iSheetIndex = null)
|
||||||
|
{
|
||||||
|
if(is_null($iSheetIndex))
|
||||||
|
{
|
||||||
|
$this->_workSheetCollection[] = $pSheet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Insert the sheet at the requested index
|
||||||
|
array_splice(
|
||||||
|
$this->_workSheetCollection,
|
||||||
|
$iSheetIndex,
|
||||||
|
0,
|
||||||
|
array($pSheet)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Adjust active sheet index if necessary
|
||||||
|
if ($this->_activeSheetIndex >= $iSheetIndex) {
|
||||||
|
++$this->_activeSheetIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return $pSheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove sheet by index
|
||||||
|
*
|
||||||
|
* @param int $pIndex Active sheet index
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function removeSheetByIndex($pIndex = 0)
|
||||||
|
{
|
||||||
|
if ($pIndex > count($this->_workSheetCollection) - 1) {
|
||||||
|
throw new Exception("Sheet index is out of bounds.");
|
||||||
|
} else {
|
||||||
|
array_splice($this->_workSheetCollection, $pIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet by index
|
||||||
|
*
|
||||||
|
* @param int $pIndex Sheet index
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getSheet($pIndex = 0)
|
||||||
|
{
|
||||||
|
if ($pIndex > count($this->_workSheetCollection) - 1) {
|
||||||
|
throw new Exception("Sheet index is out of bounds.");
|
||||||
|
} else {
|
||||||
|
return $this->_workSheetCollection[$pIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all sheets
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Worksheet[]
|
||||||
|
*/
|
||||||
|
public function getAllSheets()
|
||||||
|
{
|
||||||
|
return $this->_workSheetCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet by name
|
||||||
|
*
|
||||||
|
* @param string $pName Sheet name
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getSheetByName($pName = '')
|
||||||
|
{
|
||||||
|
$worksheetCount = count($this->_workSheetCollection);
|
||||||
|
for ($i = 0; $i < $worksheetCount; ++$i) {
|
||||||
|
if ($this->_workSheetCollection[$i]->getTitle() == $pName) {
|
||||||
|
return $this->_workSheetCollection[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get index for sheet
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Worksheet $pSheet
|
||||||
|
* @return Sheet index
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getIndex(PHPExcel_Worksheet $pSheet)
|
||||||
|
{
|
||||||
|
foreach ($this->_workSheetCollection as $key => $value) {
|
||||||
|
if ($value->getHashCode() == $pSheet->getHashCode()) {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set index for sheet by sheet name.
|
||||||
|
*
|
||||||
|
* @param string $sheetName Sheet name to modify index for
|
||||||
|
* @param int $newIndex New index for the sheet
|
||||||
|
* @return New sheet index
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function setIndexByName($sheetName, $newIndex)
|
||||||
|
{
|
||||||
|
$oldIndex = $this->getIndex($this->getSheetByName($sheetName));
|
||||||
|
$pSheet = array_splice(
|
||||||
|
$this->_workSheetCollection,
|
||||||
|
$oldIndex,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
array_splice(
|
||||||
|
$this->_workSheetCollection,
|
||||||
|
$newIndex,
|
||||||
|
0,
|
||||||
|
$pSheet
|
||||||
|
);
|
||||||
|
return $newIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet count
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getSheetCount()
|
||||||
|
{
|
||||||
|
return count($this->_workSheetCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active sheet index
|
||||||
|
*
|
||||||
|
* @return int Active sheet index
|
||||||
|
*/
|
||||||
|
public function getActiveSheetIndex()
|
||||||
|
{
|
||||||
|
return $this->_activeSheetIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set active sheet index
|
||||||
|
*
|
||||||
|
* @param int $pIndex Active sheet index
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
public function setActiveSheetIndex($pIndex = 0)
|
||||||
|
{
|
||||||
|
if ($pIndex > count($this->_workSheetCollection) - 1) {
|
||||||
|
throw new Exception("Active sheet index is out of bounds.");
|
||||||
|
} else {
|
||||||
|
$this->_activeSheetIndex = $pIndex;
|
||||||
|
}
|
||||||
|
return $this->getActiveSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set active sheet index by name
|
||||||
|
*
|
||||||
|
* @param string $pValue Sheet title
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function setActiveSheetIndexByName($pValue = '')
|
||||||
|
{
|
||||||
|
if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) {
|
||||||
|
$this->setActiveSheetIndex($worksheet->getParent()->getIndex($worksheet));
|
||||||
|
return $worksheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('Workbook does not contain sheet:' . $pValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet names
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getSheetNames()
|
||||||
|
{
|
||||||
|
$returnValue = array();
|
||||||
|
$worksheetCount = $this->getSheetCount();
|
||||||
|
for ($i = 0; $i < $worksheetCount; ++$i) {
|
||||||
|
array_push($returnValue, $this->getSheet($i)->getTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add external sheet
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Worksheet $pSheet External sheet to add
|
||||||
|
* @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) {
|
||||||
|
if (!is_null($this->getSheetByName($pSheet->getTitle()))) {
|
||||||
|
throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// count how many cellXfs there are in this workbook currently, we will need this below
|
||||||
|
$countCellXfs = count($this->_cellXfCollection);
|
||||||
|
|
||||||
|
// copy all the shared cellXfs from the external workbook and append them to the current
|
||||||
|
foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) {
|
||||||
|
$this->addCellXf(clone $cellXf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move sheet to this workbook
|
||||||
|
$pSheet->rebindParent($this);
|
||||||
|
|
||||||
|
// update the cellXfs
|
||||||
|
foreach ($pSheet->getCellCollection(false) as $cellID) {
|
||||||
|
$cell = $pSheet->getCell($cellID);
|
||||||
|
$cell->setXfIndex( $cell->getXfIndex() + $countCellXfs );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->addSheet($pSheet, $iSheetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get named ranges
|
||||||
|
*
|
||||||
|
* @return PHPExcel_NamedRange[]
|
||||||
|
*/
|
||||||
|
public function getNamedRanges() {
|
||||||
|
return $this->_namedRanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add named range
|
||||||
|
*
|
||||||
|
* @param PHPExcel_NamedRange $namedRange
|
||||||
|
* @return PHPExcel
|
||||||
|
*/
|
||||||
|
public function addNamedRange(PHPExcel_NamedRange $namedRange) {
|
||||||
|
if ($namedRange->getScope() == null) {
|
||||||
|
// global scope
|
||||||
|
$this->_namedRanges[$namedRange->getName()] = $namedRange;
|
||||||
|
} else {
|
||||||
|
// local scope
|
||||||
|
$this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get named range
|
||||||
|
*
|
||||||
|
* @param string $namedRange
|
||||||
|
* @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope
|
||||||
|
* @return PHPExcel_NamedRange|null
|
||||||
|
*/
|
||||||
|
public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
|
||||||
|
$returnValue = null;
|
||||||
|
|
||||||
|
if ($namedRange != '' && !is_null($namedRange)) {
|
||||||
|
// first look for global defined name
|
||||||
|
if (isset($this->_namedRanges[$namedRange])) {
|
||||||
|
$returnValue = $this->_namedRanges[$namedRange];
|
||||||
|
}
|
||||||
|
|
||||||
|
// then look for local defined name (has priority over global defined name if both names exist)
|
||||||
|
if (!is_null($pSheet) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
|
||||||
|
$returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove named range
|
||||||
|
*
|
||||||
|
* @param string $namedRange
|
||||||
|
* @param PHPExcel_Worksheet|null $pSheet. Scope. Use null for global scope.
|
||||||
|
* @return PHPExcel
|
||||||
|
*/
|
||||||
|
public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
|
||||||
|
if (is_null($pSheet)) {
|
||||||
|
if (isset($this->_namedRanges[$namedRange])) {
|
||||||
|
unset($this->_namedRanges[$namedRange]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
|
||||||
|
unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get worksheet iterator
|
||||||
|
*
|
||||||
|
* @return PHPExcel_WorksheetIterator
|
||||||
|
*/
|
||||||
|
public function getWorksheetIterator() {
|
||||||
|
return new PHPExcel_WorksheetIterator($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy workbook (!= clone!)
|
||||||
|
*
|
||||||
|
* @return PHPExcel
|
||||||
|
*/
|
||||||
|
public function copy() {
|
||||||
|
$copied = clone $this;
|
||||||
|
|
||||||
|
$worksheetCount = count($this->_workSheetCollection);
|
||||||
|
for ($i = 0; $i < $worksheetCount; ++$i) {
|
||||||
|
$this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy();
|
||||||
|
$this->_workSheetCollection[$i]->rebindParent($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
||||||
|
*/
|
||||||
|
public function __clone() {
|
||||||
|
foreach($this as $key => $val) {
|
||||||
|
if (is_object($val) || (is_array($val))) {
|
||||||
|
$this->{$key} = unserialize(serialize($val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the workbook collection of cellXfs
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style[]
|
||||||
|
*/
|
||||||
|
public function getCellXfCollection()
|
||||||
|
{
|
||||||
|
return $this->_cellXfCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cellXf by index
|
||||||
|
*
|
||||||
|
* @param int $index
|
||||||
|
* @return PHPExcel_Style
|
||||||
|
*/
|
||||||
|
public function getCellXfByIndex($pIndex = 0)
|
||||||
|
{
|
||||||
|
return $this->_cellXfCollection[$pIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cellXf by hash code
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_Style|false
|
||||||
|
*/
|
||||||
|
public function getCellXfByHashCode($pValue = '')
|
||||||
|
{
|
||||||
|
foreach ($this->_cellXfCollection as $cellXf) {
|
||||||
|
if ($cellXf->getHashCode() == $pValue) {
|
||||||
|
return $cellXf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default style
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getDefaultStyle()
|
||||||
|
{
|
||||||
|
if (isset($this->_cellXfCollection[0])) {
|
||||||
|
return $this->_cellXfCollection[0];
|
||||||
|
}
|
||||||
|
throw new Exception('No default style found for this workbook');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a cellXf to the workbook
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Style
|
||||||
|
*/
|
||||||
|
public function addCellXf(PHPExcel_Style $style)
|
||||||
|
{
|
||||||
|
$this->_cellXfCollection[] = $style;
|
||||||
|
$style->setIndex(count($this->_cellXfCollection) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove cellXf by index. It is ensured that all cells get their xf index updated.
|
||||||
|
*
|
||||||
|
* @param int $pIndex Index to cellXf
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function removeCellXfByIndex($pIndex = 0)
|
||||||
|
{
|
||||||
|
if ($pIndex > count($this->_cellXfCollection) - 1) {
|
||||||
|
throw new Exception("CellXf index is out of bounds.");
|
||||||
|
} else {
|
||||||
|
// first remove the cellXf
|
||||||
|
array_splice($this->_cellXfCollection, $pIndex, 1);
|
||||||
|
|
||||||
|
// then update cellXf indexes for cells
|
||||||
|
foreach ($this->_workSheetCollection as $worksheet) {
|
||||||
|
foreach ($worksheet->getCellCollection(false) as $cellID) {
|
||||||
|
$cell = $sheet->getCell($cellID);
|
||||||
|
$xfIndex = $cell->getXfIndex();
|
||||||
|
if ($xfIndex > $pIndex ) {
|
||||||
|
// decrease xf index by 1
|
||||||
|
$cell->setXfIndex($xfIndex - 1);
|
||||||
|
} else if ($xfIndex == $pIndex) {
|
||||||
|
// set to default xf index 0
|
||||||
|
$cell->setXfIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cellXf supervisor
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style
|
||||||
|
*/
|
||||||
|
public function getCellXfSupervisor()
|
||||||
|
{
|
||||||
|
return $this->_cellXfSupervisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the workbook collection of cellStyleXfs
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style[]
|
||||||
|
*/
|
||||||
|
public function getCellStyleXfCollection()
|
||||||
|
{
|
||||||
|
return $this->_cellStyleXfCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cellStyleXf by index
|
||||||
|
*
|
||||||
|
* @param int $pIndex
|
||||||
|
* @return PHPExcel_Style
|
||||||
|
*/
|
||||||
|
public function getCellStyleXfByIndex($pIndex = 0)
|
||||||
|
{
|
||||||
|
return $this->_cellStyleXfCollection[$pIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cellStyleXf by hash code
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_Style|false
|
||||||
|
*/
|
||||||
|
public function getCellStyleXfByHashCode($pValue = '')
|
||||||
|
{
|
||||||
|
foreach ($this->_cellXfStyleCollection as $cellStyleXf) {
|
||||||
|
if ($cellStyleXf->getHashCode() == $pValue) {
|
||||||
|
return $cellStyleXf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a cellStyleXf to the workbook
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Style $pStyle
|
||||||
|
*/
|
||||||
|
public function addCellStyleXf(PHPExcel_Style $pStyle)
|
||||||
|
{
|
||||||
|
$this->_cellStyleXfCollection[] = $pStyle;
|
||||||
|
$pStyle->setIndex(count($this->_cellStyleXfCollection) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove cellStyleXf by index
|
||||||
|
*
|
||||||
|
* @param int $pIndex
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function removeCellStyleXfByIndex($pIndex = 0)
|
||||||
|
{
|
||||||
|
if ($pIndex > count($this->_cellStyleXfCollection) - 1) {
|
||||||
|
throw new Exception("CellStyleXf index is out of bounds.");
|
||||||
|
} else {
|
||||||
|
array_splice($this->_cellStyleXfCollection, $pIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells
|
||||||
|
* and columns in the workbook
|
||||||
|
*/
|
||||||
|
public function garbageCollect()
|
||||||
|
{
|
||||||
|
// how many references are there to each cellXf ?
|
||||||
|
$countReferencesCellXf = array();
|
||||||
|
foreach ($this->_cellXfCollection as $index => $cellXf) {
|
||||||
|
$countReferencesCellXf[$index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->getWorksheetIterator() as $sheet) {
|
||||||
|
|
||||||
|
// from cells
|
||||||
|
foreach ($sheet->getCellCollection(false) as $cellID) {
|
||||||
|
$cell = $sheet->getCell($cellID);
|
||||||
|
++$countReferencesCellXf[$cell->getXfIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// from row dimensions
|
||||||
|
foreach ($sheet->getRowDimensions() as $rowDimension) {
|
||||||
|
if ($rowDimension->getXfIndex() !== null) {
|
||||||
|
++$countReferencesCellXf[$rowDimension->getXfIndex()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from column dimensions
|
||||||
|
foreach ($sheet->getColumnDimensions() as $columnDimension) {
|
||||||
|
++$countReferencesCellXf[$columnDimension->getXfIndex()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove cellXfs without references and create mapping so we can update xfIndex
|
||||||
|
// for all cells and columns
|
||||||
|
$countNeededCellXfs = 0;
|
||||||
|
foreach ($this->_cellXfCollection as $index => $cellXf) {
|
||||||
|
if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf
|
||||||
|
++$countNeededCellXfs;
|
||||||
|
} else {
|
||||||
|
unset($this->_cellXfCollection[$index]);
|
||||||
|
}
|
||||||
|
$map[$index] = $countNeededCellXfs - 1;
|
||||||
|
}
|
||||||
|
$this->_cellXfCollection = array_values($this->_cellXfCollection);
|
||||||
|
|
||||||
|
// update the index for all cellXfs
|
||||||
|
foreach ($this->_cellXfCollection as $i => $cellXf) {
|
||||||
|
$cellXf->setIndex($i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure there is always at least one cellXf (there should be)
|
||||||
|
if (count($this->_cellXfCollection) == 0) {
|
||||||
|
$this->_cellXfCollection[] = new PHPExcel_Style();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the xfIndex for all cells, row dimensions, column dimensions
|
||||||
|
foreach ($this->getWorksheetIterator() as $sheet) {
|
||||||
|
|
||||||
|
// for all cells
|
||||||
|
foreach ($sheet->getCellCollection(false) as $cellID) {
|
||||||
|
$cell = $sheet->getCell($cellID);
|
||||||
|
$cell->setXfIndex( $map[$cell->getXfIndex()] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// for all row dimensions
|
||||||
|
foreach ($sheet->getRowDimensions() as $rowDimension) {
|
||||||
|
if ($rowDimension->getXfIndex() !== null) {
|
||||||
|
$rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for all column dimensions
|
||||||
|
foreach ($sheet->getColumnDimensions() as $columnDimension) {
|
||||||
|
$columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// also do garbage collection for all the sheets
|
||||||
|
foreach ($this->getWorksheetIterator() as $sheet) {
|
||||||
|
$sheet->garbageCollect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PHPExcel_Autoloader
|
||||||
|
{
|
||||||
|
public static function Register() {
|
||||||
|
return spl_autoload_register(array('PHPExcel_Autoloader', 'Load'));
|
||||||
|
} // function Register()
|
||||||
|
|
||||||
|
|
||||||
|
public static function Load($pObjectName){
|
||||||
|
if ((class_exists($pObjectName)) || (strpos($pObjectName, 'PHPExcel') === False)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pObjectFilePath = PHPEXCEL_ROOT.
|
||||||
|
str_replace('_',DIRECTORY_SEPARATOR,$pObjectName).
|
||||||
|
'.php';
|
||||||
|
|
||||||
|
if ((file_exists($pObjectFilePath) === false) || (is_readable($pObjectFilePath) === false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
require($pObjectFilePath);
|
||||||
|
} // function Load()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,218 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_APC
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_APC extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
private $_cachePrefix = null;
|
||||||
|
|
||||||
|
private $_cacheTime = 600;
|
||||||
|
|
||||||
|
|
||||||
|
private function _storeData() {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
|
||||||
|
if (!apc_store($this->_cachePrefix.$this->_currentObjectID.'.cache',serialize($this->_currentObject),$this->_cacheTime)) {
|
||||||
|
$this->__destruct();
|
||||||
|
throw new Exception('Failed to store cell '.$cellID.' in APC');
|
||||||
|
}
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
} // function _storeData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) {
|
||||||
|
$this->_storeData();
|
||||||
|
}
|
||||||
|
$this->_cellCache[$pCoord] = true;
|
||||||
|
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = $cell;
|
||||||
|
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to check
|
||||||
|
* @return void
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isDataSet($pCoord) {
|
||||||
|
// Check if the requested entry is the current object, or exists in the cache
|
||||||
|
if (parent::isDataSet($pCoord)) {
|
||||||
|
if ($this->_currentObjectID == $pCoord) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Check if the requested entry still exists in apc
|
||||||
|
$success = apc_fetch($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
if ($success === false) {
|
||||||
|
// Entry no longer exists in APC, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in APC');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} // function isDataSet()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return $this->_currentObject;
|
||||||
|
}
|
||||||
|
$this->_storeData();
|
||||||
|
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
if (parent::isDataSet($pCoord)) {
|
||||||
|
$obj = apc_fetch($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
if ($obj === false) {
|
||||||
|
// Entry no longer exists in APC, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in APC');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current entry to the requested entry
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = unserialize($obj);
|
||||||
|
// Re-attach the parent worksheet
|
||||||
|
$this->_currentObject->attach($this->_parent);
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_currentObject;
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to delete
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function deleteCacheData($pCoord) {
|
||||||
|
// Delete the entry from APC
|
||||||
|
apc_delete($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
|
||||||
|
// Delete the entry from our cell address array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
} // function deleteCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the cell collection
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function copyCellCollection(PHPExcel_Worksheet $parent) {
|
||||||
|
parent::copyCellCollection($parent);
|
||||||
|
// Get a new id for the new file name
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$newCachePrefix = substr(md5($baseUnique),0,8).'.';
|
||||||
|
$cacheList = $this->getCellList();
|
||||||
|
foreach($cacheList as $cellID) {
|
||||||
|
if ($cellID != $this->_currentObjectID) {
|
||||||
|
$obj = apc_fetch($this->_cachePrefix.$cellID.'.cache');
|
||||||
|
if ($obj === false) {
|
||||||
|
// Entry no longer exists in APC, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($cellID);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in APC');
|
||||||
|
}
|
||||||
|
if (!apc_store($newCachePrefix.$cellID.'.cache',$obj,$this->_cacheTime)) {
|
||||||
|
$this->__destruct();
|
||||||
|
throw new Exception('Failed to store cell '.$cellID.' in APC');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_cachePrefix = $newCachePrefix;
|
||||||
|
} // function copyCellCollection()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
if(!is_null($this->_currentObject)) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObject = $this->_currentObjectID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the APC cache
|
||||||
|
$this->__destruct();
|
||||||
|
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(PHPExcel_Worksheet $parent, $arguments) {
|
||||||
|
$cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600;
|
||||||
|
|
||||||
|
if (is_null($this->_cachePrefix)) {
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$this->_cachePrefix = substr(md5($baseUnique),0,8).'.';
|
||||||
|
$this->_cacheTime = $cacheTime;
|
||||||
|
|
||||||
|
parent::__construct($parent);
|
||||||
|
}
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$cacheList = $this->getCellList();
|
||||||
|
foreach($cacheList as $cellID) {
|
||||||
|
apc_delete($this->_cachePrefix.$cellID.'.cache');
|
||||||
|
}
|
||||||
|
} // function __destruct()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_CacheBase
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_CacheBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent worksheet
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
protected $_parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently active Cell
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
protected $_currentObject = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coordinate address of the currently active Cell
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $_currentObjectID = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of cells or cell pointers for the worksheet cells held in this cache,
|
||||||
|
* and indexed by their coordinate address within the worksheet
|
||||||
|
*
|
||||||
|
* @var array of mixed
|
||||||
|
*/
|
||||||
|
protected $_cellCache = array();
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(PHPExcel_Worksheet $parent) {
|
||||||
|
// Set our parent worksheet.
|
||||||
|
// This is maintained within the cache controller to facilitate re-attaching it to PHPExcel_Cell objects when
|
||||||
|
// they are woken from a serialized state
|
||||||
|
$this->_parent = $parent;
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to check
|
||||||
|
* @return void
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isDataSet($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Check if the requested entry exists in the cache
|
||||||
|
return isset($this->_cellCache[$pCoord]);
|
||||||
|
} // function isDataSet()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function updateCacheData(PHPExcel_Cell $cell) {
|
||||||
|
$pCoord = $cell->getCoordinate();
|
||||||
|
|
||||||
|
return $this->addCacheData($pCoord,$cell);
|
||||||
|
} // function updateCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to delete
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function deleteCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_object($this->_cellCache[$pCoord])) {
|
||||||
|
$this->_cellCache[$pCoord]->detach();
|
||||||
|
unset($this->_cellCache[$pCoord]);
|
||||||
|
}
|
||||||
|
} // function deleteCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of all cell addresses currently held in cache
|
||||||
|
*
|
||||||
|
* @return array of string
|
||||||
|
*/
|
||||||
|
public function getCellList() {
|
||||||
|
return array_keys($this->_cellCache);
|
||||||
|
} // function getCellList()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the list of all cell addresses currently held in cache by row and column
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function getSortedCellList() {
|
||||||
|
$sortKeys = array();
|
||||||
|
foreach ($this->_cellCache as $coord => $value) {
|
||||||
|
list($colNum,$rowNum) = sscanf($coord,'%[A-Z]%d');
|
||||||
|
$sortKeys[sprintf('%09d%3s',$rowNum,$colNum)] = $coord;
|
||||||
|
}
|
||||||
|
ksort($sortKeys);
|
||||||
|
|
||||||
|
return array_values($sortKeys);
|
||||||
|
} // function sortCellList()
|
||||||
|
|
||||||
|
|
||||||
|
protected function _getUniqueID() {
|
||||||
|
if (function_exists('posix_getpid')) {
|
||||||
|
$baseUnique = posix_getpid();
|
||||||
|
} else {
|
||||||
|
$baseUnique = mt_rand();
|
||||||
|
}
|
||||||
|
return uniqid($baseUnique,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the cell collection
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function copyCellCollection(PHPExcel_Worksheet $parent) {
|
||||||
|
$this->_parent = $parent;
|
||||||
|
if ((!is_null($this->_currentObject)) && (is_object($this->_currentObject))) {
|
||||||
|
$this->_currentObject->attach($parent);
|
||||||
|
}
|
||||||
|
} // function copyCellCollection()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_DiscISAM
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
private $_fileName = null;
|
||||||
|
private $_fileHandle = null;
|
||||||
|
|
||||||
|
|
||||||
|
private function _storeData() {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
|
||||||
|
fseek($this->_fileHandle,0,SEEK_END);
|
||||||
|
$offset = ftell($this->_fileHandle);
|
||||||
|
fwrite($this->_fileHandle, serialize($this->_currentObject));
|
||||||
|
$this->_cellCache[$this->_currentObjectID] = array('ptr' => $offset,
|
||||||
|
'sz' => ftell($this->_fileHandle) - $offset
|
||||||
|
);
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
} // function _storeData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) {
|
||||||
|
$this->_storeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = $cell;
|
||||||
|
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return $this->_currentObject;
|
||||||
|
}
|
||||||
|
$this->_storeData();
|
||||||
|
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
if (!isset($this->_cellCache[$pCoord])) {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current entry to the requested entry
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']);
|
||||||
|
$this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz']));
|
||||||
|
// Re-attach the parent worksheet
|
||||||
|
$this->_currentObject->attach($this->_parent);
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_currentObject;
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the cell collection
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function copyCellCollection(PHPExcel_Worksheet $parent) {
|
||||||
|
parent::copyCellCollection($parent);
|
||||||
|
// Get a new id for the new file name
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$newFileName = sys_get_temp_dir().'/PHPExcel.'.$baseUnique.'.cache';
|
||||||
|
// Copy the existing cell cache file
|
||||||
|
copy ($this->_fileName,$newFileName);
|
||||||
|
$this->_fileName = $newFileName;
|
||||||
|
// Open the copied cell cache file
|
||||||
|
$this->_fileHandle = fopen($this->_fileName,'a+');
|
||||||
|
} // function copyCellCollection()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
if(!is_null($this->_currentObject)) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObject = $this->_currentObjectID = null;
|
||||||
|
}
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
|
||||||
|
// Close down the temporary cache file
|
||||||
|
$this->__destruct();
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(PHPExcel_Worksheet $parent) {
|
||||||
|
parent::__construct($parent);
|
||||||
|
if (is_null($this->_fileHandle)) {
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$this->_fileName = sys_get_temp_dir().'/PHPExcel.'.$baseUnique.'.cache';
|
||||||
|
$this->_fileHandle = fopen($this->_fileName,'a+');
|
||||||
|
}
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
if (!is_null($this->_fileHandle)) {
|
||||||
|
fclose($this->_fileHandle);
|
||||||
|
unlink($this->_fileName);
|
||||||
|
}
|
||||||
|
$this->_fileHandle = null;
|
||||||
|
} // function __destruct()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_ICache
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
interface PHPExcel_CachedObjectStorage_ICache
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function updateCacheData(PHPExcel_Cell $cell);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a cell from cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to retrieve
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to delete
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function deleteCacheData($pCoord);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to check
|
||||||
|
* @return void
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isDataSet($pCoord);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of all cell addresses currently held in cache
|
||||||
|
*
|
||||||
|
* @return array of string
|
||||||
|
*/
|
||||||
|
public function getCellList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of all cell addresses currently held in cache sorted by column and row
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function getSortedCellList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the cell collection
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function copyCellCollection(PHPExcel_Worksheet $parent);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,239 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_Memcache
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
private $_cachePrefix = null;
|
||||||
|
|
||||||
|
private $_cacheTime = 600;
|
||||||
|
|
||||||
|
private $_memcache = null;
|
||||||
|
|
||||||
|
|
||||||
|
private function _storeData() {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
|
||||||
|
$obj = serialize($this->_currentObject);
|
||||||
|
if (!$this->_memcache->replace($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) {
|
||||||
|
if (!$this->_memcache->add($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) {
|
||||||
|
$this->__destruct();
|
||||||
|
throw new Exception('Failed to store cell '.$cellID.' in MemCache');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
} // function _storeData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) {
|
||||||
|
$this->_storeData();
|
||||||
|
}
|
||||||
|
$this->_cellCache[$pCoord] = true;
|
||||||
|
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = $cell;
|
||||||
|
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to check
|
||||||
|
* @return void
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isDataSet($pCoord) {
|
||||||
|
// Check if the requested entry is the current object, or exists in the cache
|
||||||
|
if (parent::isDataSet($pCoord)) {
|
||||||
|
if ($this->_currentObjectID == $pCoord) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Check if the requested entry still exists in Memcache
|
||||||
|
$success = $this->_memcache->get($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
if ($success === false) {
|
||||||
|
// Entry no longer exists in Memcache, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in MemCache');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} // function isDataSet()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return $this->_currentObject;
|
||||||
|
}
|
||||||
|
$this->_storeData();
|
||||||
|
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
if (parent::isDataSet($pCoord)) {
|
||||||
|
$obj = $this->_memcache->get($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
if ($obj === false) {
|
||||||
|
// Entry no longer exists in Memcache, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in MemCache');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current entry to the requested entry
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = unserialize($obj);
|
||||||
|
// Re-attach the parent worksheet
|
||||||
|
$this->_currentObject->attach($this->_parent);
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_currentObject;
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to delete
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function deleteCacheData($pCoord) {
|
||||||
|
// Delete the entry from Memcache
|
||||||
|
$this->_memcache->delete($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
|
||||||
|
// Delete the entry from our cell address array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
} // function deleteCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the cell collection
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function copyCellCollection(PHPExcel_Worksheet $parent) {
|
||||||
|
parent::copyCellCollection($parent);
|
||||||
|
// Get a new id for the new file name
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$newCachePrefix = substr(md5($baseUnique),0,8).'.';
|
||||||
|
$cacheList = $this->getCellList();
|
||||||
|
foreach($cacheList as $cellID) {
|
||||||
|
if ($cellID != $this->_currentObjectID) {
|
||||||
|
$obj = $this->_memcache->get($this->_cachePrefix.$cellID.'.cache');
|
||||||
|
if ($obj === false) {
|
||||||
|
// Entry no longer exists in Memcache, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($cellID);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in MemCache');
|
||||||
|
}
|
||||||
|
if (!$this->_memcache->add($newCachePrefix.$cellID.'.cache',$obj,NULL,$this->_cacheTime)) {
|
||||||
|
$this->__destruct();
|
||||||
|
throw new Exception('Failed to store cell '.$cellID.' in MemCache');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_cachePrefix = $newCachePrefix;
|
||||||
|
} // function copyCellCollection()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
if(!is_null($this->_currentObject)) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObject = $this->_currentObjectID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the Memcache cache
|
||||||
|
$this->__destruct();
|
||||||
|
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(PHPExcel_Worksheet $parent, $arguments) {
|
||||||
|
$memcacheServer = (isset($arguments['memcacheServer'])) ? $arguments['memcacheServer'] : 'localhost';
|
||||||
|
$memcachePort = (isset($arguments['memcachePort'])) ? $arguments['memcachePort'] : 11211;
|
||||||
|
$cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600;
|
||||||
|
|
||||||
|
if (is_null($this->_cachePrefix)) {
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$this->_cachePrefix = substr(md5($baseUnique),0,8).'.';
|
||||||
|
|
||||||
|
// Set a new Memcache object and connect to the Memcache server
|
||||||
|
$this->_memcache = new Memcache();
|
||||||
|
if (!$this->_memcache->addServer($memcacheServer, $memcachePort, false, 50, 5, 5, true, array($this, 'failureCallback'))) {
|
||||||
|
throw new Exception('Could not connect to MemCache server at '.$memcacheServer.':'.$memcachePort);
|
||||||
|
}
|
||||||
|
$this->_cacheTime = $cacheTime;
|
||||||
|
|
||||||
|
parent::__construct($parent);
|
||||||
|
}
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
|
||||||
|
public function failureCallback($host, $port) {
|
||||||
|
throw new Exception('memcache '.$host.':'.$port.' failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$cacheList = $this->getCellList();
|
||||||
|
foreach($cacheList as $cellID) {
|
||||||
|
$this->_memcache->delete($this->_cachePrefix.$cellID.'.cache');
|
||||||
|
}
|
||||||
|
} // function __destruct()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_Memory
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
$this->_cellCache[$pCoord] = $cell;
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
if (!isset($this->_cellCache[$pCoord])) {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_cellCache[$pCoord];
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
// Because cells are all stored as intact objects in memory, we need to detach each one from the parent
|
||||||
|
foreach($this->_cellCache as $k => &$cell) {
|
||||||
|
$cell->detach();
|
||||||
|
$this->_cellCache[$k] = null;
|
||||||
|
}
|
||||||
|
unset($cell);
|
||||||
|
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_MemoryGZip
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
private function _storeData() {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
|
||||||
|
$this->_cellCache[$this->_currentObjectID] = gzdeflate(serialize($this->_currentObject));
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
} // function _storeData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) {
|
||||||
|
$this->_storeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = $cell;
|
||||||
|
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return $this->_currentObject;
|
||||||
|
}
|
||||||
|
$this->_storeData();
|
||||||
|
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
if (!isset($this->_cellCache[$pCoord])) {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current entry to the requested entry
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = unserialize(gzinflate($this->_cellCache[$pCoord]));
|
||||||
|
// Re-attach the parent worksheet
|
||||||
|
$this->_currentObject->attach($this->_parent);
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_currentObject;
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
if(!is_null($this->_currentObject)) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObject = $this->_currentObjectID = null;
|
||||||
|
}
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_MemorySerialized
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
private function _storeData() {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
|
||||||
|
$this->_cellCache[$this->_currentObjectID] = serialize($this->_currentObject);
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
} // function _storeData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) {
|
||||||
|
$this->_storeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = $cell;
|
||||||
|
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return $this->_currentObject;
|
||||||
|
}
|
||||||
|
$this->_storeData();
|
||||||
|
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
if (!isset($this->_cellCache[$pCoord])) {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current entry to the requested entry
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = unserialize($this->_cellCache[$pCoord]);
|
||||||
|
// Re-attach the parent worksheet
|
||||||
|
$this->_currentObject->attach($this->_parent);
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_currentObject;
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
if(!is_null($this->_currentObject)) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObject = $this->_currentObjectID = null;
|
||||||
|
}
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_PHPTemp
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
private $_fileHandle = null;
|
||||||
|
|
||||||
|
|
||||||
|
private $_memoryCacheSize = null;
|
||||||
|
|
||||||
|
private function _storeData() {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
|
||||||
|
fseek($this->_fileHandle,0,SEEK_END);
|
||||||
|
$offset = ftell($this->_fileHandle);
|
||||||
|
fwrite($this->_fileHandle, serialize($this->_currentObject));
|
||||||
|
$this->_cellCache[$this->_currentObjectID] = array('ptr' => $offset,
|
||||||
|
'sz' => ftell($this->_fileHandle) - $offset
|
||||||
|
);
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
} // function _storeData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) {
|
||||||
|
$this->_storeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = $cell;
|
||||||
|
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return $this->_currentObject;
|
||||||
|
}
|
||||||
|
$this->_storeData();
|
||||||
|
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
if (!isset($this->_cellCache[$pCoord])) {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current entry to the requested entry
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']);
|
||||||
|
$this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz']));
|
||||||
|
// Re-attach the parent worksheet
|
||||||
|
$this->_currentObject->attach($this->_parent);
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_currentObject;
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the cell collection
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function copyCellCollection(PHPExcel_Worksheet $parent) {
|
||||||
|
parent::copyCellCollection($parent);
|
||||||
|
// Open a new stream for the cell cache data
|
||||||
|
$newFileHandle = fopen('php://temp/maxmemory:'.$this->_memoryCacheSize,'a+');
|
||||||
|
// Copy the existing cell cache data to the new stream
|
||||||
|
fseek($this->_fileHandle,0);
|
||||||
|
while (!feof($this->_fileHandle)) {
|
||||||
|
fwrite($newFileHandle,fread($this->_fileHandle, 1024));
|
||||||
|
}
|
||||||
|
$this->_fileHandle = $newFileHandle;
|
||||||
|
} // function copyCellCollection()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
if(!is_null($this->_currentObject)) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObject = $this->_currentObjectID = null;
|
||||||
|
}
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
|
||||||
|
// Close down the php://temp file
|
||||||
|
$this->__destruct();
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(PHPExcel_Worksheet $parent, $memoryCacheSize = '1MB') {
|
||||||
|
$this->_memoryCacheSize = (isset($arguments['memoryCacheSize'])) ? $arguments['memoryCacheSize'] : '1MB';
|
||||||
|
|
||||||
|
parent::__construct($parent);
|
||||||
|
if (is_null($this->_fileHandle)) {
|
||||||
|
$this->_fileHandle = fopen('php://temp/maxmemory:'.$this->_memoryCacheSize,'a+');
|
||||||
|
}
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
if (!is_null($this->_fileHandle)) {
|
||||||
|
fclose($this->_fileHandle);
|
||||||
|
}
|
||||||
|
$this->_fileHandle = null;
|
||||||
|
} // function __destruct()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,233 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_CachedObjectStorage_Wincache
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_CachedObjectStorage
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache {
|
||||||
|
|
||||||
|
private $_cachePrefix = null;
|
||||||
|
|
||||||
|
private $_cacheTime = 600;
|
||||||
|
|
||||||
|
|
||||||
|
private function _storeData() {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
|
||||||
|
$obj = serialize($this->_currentObject);
|
||||||
|
if (wincache_ucache_exists($this->_cachePrefix.$this->_currentObjectID.'.cache')) {
|
||||||
|
if (!wincache_ucache_set($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime)) {
|
||||||
|
$this->__destruct();
|
||||||
|
throw new Exception('Failed to store cell '.$cellID.' in WinCache');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!wincache_ucache_add($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime)) {
|
||||||
|
$this->__destruct();
|
||||||
|
throw new Exception('Failed to store cell '.$cellID.' in WinCache');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_currentObjectID = $this->_currentObject = null;
|
||||||
|
} // function _storeData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add or Update a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to update
|
||||||
|
* @param PHPExcel_Cell $cell Cell to update
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addCacheData($pCoord, PHPExcel_Cell $cell) {
|
||||||
|
if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) {
|
||||||
|
$this->_storeData();
|
||||||
|
}
|
||||||
|
$this->_cellCache[$pCoord] = true;
|
||||||
|
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = $cell;
|
||||||
|
|
||||||
|
return $cell;
|
||||||
|
} // function addCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell?
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to check
|
||||||
|
* @return void
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isDataSet($pCoord) {
|
||||||
|
// Check if the requested entry is the current object, or exists in the cache
|
||||||
|
if (parent::isDataSet($pCoord)) {
|
||||||
|
if ($this->_currentObjectID == $pCoord) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Check if the requested entry still exists in cache
|
||||||
|
$success = wincache_ucache_exists($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
if ($success === false) {
|
||||||
|
// Entry no longer exists in Wincache, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in WinCache');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} // function isDataSet()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell at a specific coordinate
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate of the cell
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell Cell that was found, or null if not found
|
||||||
|
*/
|
||||||
|
public function getCacheData($pCoord) {
|
||||||
|
if ($pCoord === $this->_currentObjectID) {
|
||||||
|
return $this->_currentObject;
|
||||||
|
}
|
||||||
|
$this->_storeData();
|
||||||
|
|
||||||
|
// Check if the entry that has been requested actually exists
|
||||||
|
$obj = null;
|
||||||
|
if (parent::isDataSet($pCoord)) {
|
||||||
|
$success = false;
|
||||||
|
$obj = wincache_ucache_get($this->_cachePrefix.$pCoord.'.cache', $success);
|
||||||
|
if ($success === false) {
|
||||||
|
// Entry no longer exists in WinCache, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in WinCache');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Return null if requested entry doesn't exist in cache
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current entry to the requested entry
|
||||||
|
$this->_currentObjectID = $pCoord;
|
||||||
|
$this->_currentObject = unserialize($obj);
|
||||||
|
// Re-attach the parent worksheet
|
||||||
|
$this->_currentObject->attach($this->_parent);
|
||||||
|
|
||||||
|
// Return requested entry
|
||||||
|
return $this->_currentObject;
|
||||||
|
} // function getCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a cell in cache identified by coordinate address
|
||||||
|
*
|
||||||
|
* @param string $pCoord Coordinate address of the cell to delete
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function deleteCacheData($pCoord) {
|
||||||
|
// Delete the entry from Wincache
|
||||||
|
wincache_ucache_delete($this->_cachePrefix.$pCoord.'.cache');
|
||||||
|
|
||||||
|
// Delete the entry from our cell address array
|
||||||
|
parent::deleteCacheData($pCoord);
|
||||||
|
} // function deleteCacheData()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the cell collection
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function copyCellCollection(PHPExcel_Worksheet $parent) {
|
||||||
|
parent::copyCellCollection($parent);
|
||||||
|
// Get a new id for the new file name
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$newCachePrefix = substr(md5($baseUnique),0,8).'.';
|
||||||
|
$cacheList = $this->getCellList();
|
||||||
|
foreach($cacheList as $cellID) {
|
||||||
|
if ($cellID != $this->_currentObjectID) {
|
||||||
|
$success = false;
|
||||||
|
$obj = wincache_ucache_get($this->_cachePrefix.$cellID.'.cache', $success);
|
||||||
|
if ($success === false) {
|
||||||
|
// Entry no longer exists in WinCache, so clear it from the cache array
|
||||||
|
parent::deleteCacheData($cellID);
|
||||||
|
throw new Exception('Cell entry '.$cellID.' no longer exists in Wincache');
|
||||||
|
}
|
||||||
|
if (!wincache_ucache_add($newCachePrefix.$cellID.'.cache', $obj, $this->_cacheTime)) {
|
||||||
|
$this->__destruct();
|
||||||
|
throw new Exception('Failed to store cell '.$cellID.' in Wincache');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_cachePrefix = $newCachePrefix;
|
||||||
|
} // function copyCellCollection()
|
||||||
|
|
||||||
|
|
||||||
|
public function unsetWorksheetCells() {
|
||||||
|
if(!is_null($this->_currentObject)) {
|
||||||
|
$this->_currentObject->detach();
|
||||||
|
$this->_currentObject = $this->_currentObjectID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the WinCache cache
|
||||||
|
$this->__destruct();
|
||||||
|
|
||||||
|
$this->_cellCache = array();
|
||||||
|
|
||||||
|
// detach ourself from the worksheet, so that it can then delete this object successfully
|
||||||
|
$this->_parent = null;
|
||||||
|
} // function unsetWorksheetCells()
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(PHPExcel_Worksheet $parent, $arguments) {
|
||||||
|
$cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600;
|
||||||
|
|
||||||
|
if (is_null($this->_cachePrefix)) {
|
||||||
|
$baseUnique = $this->_getUniqueID();
|
||||||
|
$this->_cachePrefix = substr(md5($baseUnique),0,8).'.';
|
||||||
|
$this->_cacheTime = $cacheTime;
|
||||||
|
|
||||||
|
parent::__construct($parent);
|
||||||
|
}
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$cacheList = $this->getCellList();
|
||||||
|
foreach($cacheList as $cellID) {
|
||||||
|
wincache_ucache_delete($this->_cachePrefix.$cellID.'.cache');
|
||||||
|
}
|
||||||
|
} // function __destruct()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class PHPExcel_CachedObjectStorageFactory {
|
||||||
|
const cache_in_memory = 'Memory';
|
||||||
|
const cache_in_memory_gzip = 'MemoryGZip';
|
||||||
|
const cache_in_memory_serialized = 'MemorySerialized';
|
||||||
|
const cache_to_discISAM = 'DiscISAM';
|
||||||
|
const cache_to_apc = 'APC';
|
||||||
|
const cache_to_memcache = 'Memcache';
|
||||||
|
const cache_to_phpTemp = 'PHPTemp';
|
||||||
|
const cache_to_wincache = 'Wincache';
|
||||||
|
|
||||||
|
|
||||||
|
private static $_cacheStorageMethod = null;
|
||||||
|
|
||||||
|
private static $_cacheStorageClass = null;
|
||||||
|
|
||||||
|
|
||||||
|
private static $_storageMethods = array(
|
||||||
|
self::cache_in_memory,
|
||||||
|
self::cache_in_memory_gzip,
|
||||||
|
self::cache_in_memory_serialized,
|
||||||
|
self::cache_to_phpTemp,
|
||||||
|
self::cache_to_discISAM,
|
||||||
|
self::cache_to_apc,
|
||||||
|
self::cache_to_memcache,
|
||||||
|
self::cache_to_wincache,
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
private static $_storageMethodDefaultParameters = array(
|
||||||
|
self::cache_in_memory => array(
|
||||||
|
),
|
||||||
|
self::cache_in_memory_gzip => array(
|
||||||
|
),
|
||||||
|
self::cache_in_memory_serialized => array(
|
||||||
|
),
|
||||||
|
self::cache_to_phpTemp => array( 'memoryCacheSize' => '1MB'
|
||||||
|
),
|
||||||
|
self::cache_to_discISAM => array(
|
||||||
|
),
|
||||||
|
self::cache_to_apc => array( 'cacheTime' => 600
|
||||||
|
),
|
||||||
|
self::cache_to_memcache => array( 'memcacheServer' => 'localhost',
|
||||||
|
'memcachePort' => 11211,
|
||||||
|
'cacheTime' => 600
|
||||||
|
),
|
||||||
|
self::cache_to_wincache => array( 'cacheTime' => 600
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
private static $_storageMethodParameters = array();
|
||||||
|
|
||||||
|
|
||||||
|
public static function getCacheStorageMethod() {
|
||||||
|
if (!is_null(self::$_cacheStorageMethod)) {
|
||||||
|
return self::$_cacheStorageMethod;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} // function getCacheStorageMethod()
|
||||||
|
|
||||||
|
|
||||||
|
public static function getCacheStorageClass() {
|
||||||
|
if (!is_null(self::$_cacheStorageClass)) {
|
||||||
|
return self::$_cacheStorageClass;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} // function getCacheStorageClass()
|
||||||
|
|
||||||
|
|
||||||
|
public static function getCacheStorageMethods() {
|
||||||
|
return self::$_storageMethods;
|
||||||
|
} // function getCacheStorageMethods()
|
||||||
|
|
||||||
|
|
||||||
|
public static function initialize($method = self::cache_in_memory, $arguments = array()) {
|
||||||
|
if (!in_array($method,self::$_storageMethods)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch($method) {
|
||||||
|
case self::cache_to_apc :
|
||||||
|
if (!function_exists('apc_store')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (apc_sma_info() === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case self::cache_to_memcache :
|
||||||
|
if (!function_exists('memcache_add')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case self::cache_to_wincache :
|
||||||
|
if (!function_exists('wincache_ucache_add')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$_storageMethodParameters[$method] = self::$_storageMethodDefaultParameters[$method];
|
||||||
|
foreach($arguments as $k => $v) {
|
||||||
|
if (isset(self::$_storageMethodParameters[$method][$k])) {
|
||||||
|
self::$_storageMethodParameters[$method][$k] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null(self::$_cacheStorageMethod)) {
|
||||||
|
self::$_cacheStorageClass = 'PHPExcel_CachedObjectStorage_'.$method;
|
||||||
|
self::$_cacheStorageMethod = $method;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // function initialize()
|
||||||
|
|
||||||
|
|
||||||
|
public static function getInstance(PHPExcel_Worksheet $parent) {
|
||||||
|
if (is_null(self::$_cacheStorageMethod)) {
|
||||||
|
self::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
$instance = new self::$_cacheStorageClass($parent,self::$_storageMethodParameters[self::$_cacheStorageMethod]);
|
||||||
|
if (!is_null($instance)) {
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // function getInstance()
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Calculation_Exception
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Calculation_Exception extends 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,49 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Calculation_ExceptionHandler
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Calculation_ExceptionHandler {
|
||||||
|
/**
|
||||||
|
* Register errorhandler
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
set_error_handler(array('PHPExcel_Calculation_Exception', 'errorHandlerCallback'), E_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister errorhandler
|
||||||
|
*/
|
||||||
|
public function __destruct() {
|
||||||
|
restore_error_handler();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,614 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
PARTLY BASED ON:
|
||||||
|
Copyright (c) 2007 E. W. Bachtal, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||||
|
portions of the Software.
|
||||||
|
|
||||||
|
The software is provided "as is", without warranty of any kind, express or implied, including but not
|
||||||
|
limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In
|
||||||
|
no event shall the authors or copyright holders be liable for any claim, damages or other liability,
|
||||||
|
whether in an action of contract, tort or otherwise, arising from, out of or in connection with the
|
||||||
|
software or the use or other dealings in the software.
|
||||||
|
|
||||||
|
http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html
|
||||||
|
http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Calculation_FormulaParser
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Calculation_FormulaParser {
|
||||||
|
/* Character constants */
|
||||||
|
const QUOTE_DOUBLE = '"';
|
||||||
|
const QUOTE_SINGLE = '\'';
|
||||||
|
const BRACKET_CLOSE = ']';
|
||||||
|
const BRACKET_OPEN = '[';
|
||||||
|
const BRACE_OPEN = '{';
|
||||||
|
const BRACE_CLOSE = '}';
|
||||||
|
const PAREN_OPEN = '(';
|
||||||
|
const PAREN_CLOSE = ')';
|
||||||
|
const SEMICOLON = ';';
|
||||||
|
const WHITESPACE = ' ';
|
||||||
|
const COMMA = ',';
|
||||||
|
const ERROR_START = '#';
|
||||||
|
|
||||||
|
const OPERATORS_SN = "+-";
|
||||||
|
const OPERATORS_INFIX = "+-*/^&=><";
|
||||||
|
const OPERATORS_POSTFIX = "%";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formula
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_formula;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokens
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Calculation_FormulaToken[]
|
||||||
|
*/
|
||||||
|
private $_tokens = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Calculation_FormulaParser
|
||||||
|
*
|
||||||
|
* @param string $pFormula Formula to parse
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct($pFormula = '')
|
||||||
|
{
|
||||||
|
// Check parameters
|
||||||
|
if (is_null($pFormula)) {
|
||||||
|
throw new Exception("Invalid parameter passed: formula");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise values
|
||||||
|
$this->_formula = trim($pFormula);
|
||||||
|
// Parse!
|
||||||
|
$this->_parseToTokens();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Formula
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFormula() {
|
||||||
|
return $this->_formula;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Token
|
||||||
|
*
|
||||||
|
* @param int $pId Token id
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getToken($pId = 0) {
|
||||||
|
if (isset($this->_tokens[$pId])) {
|
||||||
|
return $this->_tokens[$pId];
|
||||||
|
} else {
|
||||||
|
throw new Exception("Token with id $pId does not exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Token count
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTokenCount() {
|
||||||
|
return count($this->_tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Tokens
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Calculation_FormulaToken[]
|
||||||
|
*/
|
||||||
|
public function getTokens() {
|
||||||
|
return $this->_tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse to tokens
|
||||||
|
*/
|
||||||
|
private function _parseToTokens() {
|
||||||
|
// No attempt is made to verify formulas; assumes formulas are derived from Excel, where
|
||||||
|
// they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions.
|
||||||
|
|
||||||
|
// Check if the formula has a valid starting =
|
||||||
|
$formulaLength = strlen($this->_formula);
|
||||||
|
if ($formulaLength < 2 || $this->_formula{0} != '=') return;
|
||||||
|
|
||||||
|
// Helper variables
|
||||||
|
$tokens1 = $tokens2 = $stack = array();
|
||||||
|
$inString = $inPath = $inRange = $inError = false;
|
||||||
|
$token = $previousToken = $nextToken = null;
|
||||||
|
|
||||||
|
$index = 1;
|
||||||
|
$value = '';
|
||||||
|
|
||||||
|
$ERRORS = array("#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A");
|
||||||
|
$COMPARATORS_MULTI = array(">=", "<=", "<>");
|
||||||
|
|
||||||
|
while ($index < $formulaLength) {
|
||||||
|
// state-dependent character evaluation (order is important)
|
||||||
|
|
||||||
|
// double-quoted strings
|
||||||
|
// embeds are doubled
|
||||||
|
// end marks token
|
||||||
|
if ($inString) {
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
|
||||||
|
if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE)) {
|
||||||
|
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE;
|
||||||
|
++$index;
|
||||||
|
} else {
|
||||||
|
$inString = false;
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_TEXT);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$value .= $this->_formula{$index};
|
||||||
|
}
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// single-quoted strings (links)
|
||||||
|
// embeds are double
|
||||||
|
// end does not mark a token
|
||||||
|
if ($inPath) {
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
|
||||||
|
if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE)) {
|
||||||
|
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE;
|
||||||
|
++$index;
|
||||||
|
} else {
|
||||||
|
$inPath = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$value .= $this->_formula{$index};
|
||||||
|
}
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bracked strings (R1C1 range index or linked workbook name)
|
||||||
|
// no embeds (changed to "()" by Excel)
|
||||||
|
// end does not mark a token
|
||||||
|
if ($inRange) {
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE) {
|
||||||
|
$inRange = false;
|
||||||
|
}
|
||||||
|
$value .= $this->_formula{$index};
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// error values
|
||||||
|
// end marks a token, determined from absolute list of values
|
||||||
|
if ($inError) {
|
||||||
|
$value .= $this->_formula{$index};
|
||||||
|
++$index;
|
||||||
|
if (in_array($value, $ERRORS)) {
|
||||||
|
$inError = false;
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_ERROR);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scientific notation check
|
||||||
|
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_SN, $this->_formula{$index}) !== false) {
|
||||||
|
if (strlen($value) > 1) {
|
||||||
|
if (preg_match("/^[1-9]{1}(\.[0-9]+)?E{1}$/", $this->_formula{$index}) != 0) {
|
||||||
|
$value .= $this->_formula{$index};
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// independent character evaluation (order not important)
|
||||||
|
|
||||||
|
// establish state-dependent character evaluations
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
|
||||||
|
if (strlen($value > 0)) { // unexpected
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
$inString = true;
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
|
||||||
|
if (strlen($value) > 0) { // unexpected
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
$inPath = true;
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_OPEN) {
|
||||||
|
$inRange = true;
|
||||||
|
$value .= PHPExcel_Calculation_FormulaParser::BRACKET_OPEN;
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::ERROR_START) {
|
||||||
|
if (strlen($value) > 0) { // unexpected
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
$inError = true;
|
||||||
|
$value .= PHPExcel_Calculation_FormulaParser::ERROR_START;
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark start and end of arrays and array rows
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_OPEN) {
|
||||||
|
if (strlen($value) > 0) { // unexpected
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAY", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
$stack[] = clone $tmp;
|
||||||
|
|
||||||
|
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
$stack[] = clone $tmp;
|
||||||
|
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::SEMICOLON) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = array_pop($stack);
|
||||||
|
$tmp->setValue("");
|
||||||
|
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
|
||||||
|
$tmp = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
|
||||||
|
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
$stack[] = clone $tmp;
|
||||||
|
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_CLOSE) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = array_pop($stack);
|
||||||
|
$tmp->setValue("");
|
||||||
|
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
|
||||||
|
$tmp = array_pop($stack);
|
||||||
|
$tmp->setValue("");
|
||||||
|
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim white-space
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE);
|
||||||
|
++$index;
|
||||||
|
while (($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) && ($index < $formulaLength)) {
|
||||||
|
++$index;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// multi-character comparators
|
||||||
|
if (($index + 2) <= $formulaLength) {
|
||||||
|
if (in_array(substr($this->_formula, $index, 2), $COMPARATORS_MULTI)) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken(substr($this->_formula, $index, 2), PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
|
||||||
|
$index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// standard infix operators
|
||||||
|
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX, $this->_formula{$index}) !== false) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] =new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX);
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// standard postfix operators (only one)
|
||||||
|
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX, $this->_formula{$index}) !== false) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX);
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start subexpression or function
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_OPEN) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tmp = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
$stack[] = clone $tmp;
|
||||||
|
$value = "";
|
||||||
|
} else {
|
||||||
|
$tmp = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
$stack[] = clone $tmp;
|
||||||
|
}
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// function, subexpression, or array parameters, or operand unions
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::COMMA) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = array_pop($stack);
|
||||||
|
$tmp->setValue("");
|
||||||
|
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
|
||||||
|
$stack[] = $tmp;
|
||||||
|
|
||||||
|
if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_UNION);
|
||||||
|
} else {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
|
||||||
|
}
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop subexpression
|
||||||
|
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_CLOSE) {
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
$value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = array_pop($stack);
|
||||||
|
$tmp->setValue("");
|
||||||
|
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
|
||||||
|
$tokens1[] = $tmp;
|
||||||
|
|
||||||
|
++$index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// token accumulation
|
||||||
|
$value .= $this->_formula{$index};
|
||||||
|
++$index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump remaining accumulation
|
||||||
|
if (strlen($value) > 0) {
|
||||||
|
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move tokenList to new set, excluding unnecessary white-space tokens and converting necessary ones to intersections
|
||||||
|
$tokenCount = count($tokens1);
|
||||||
|
for ($i = 0; $i < $tokenCount; ++$i) {
|
||||||
|
$token = $tokens1[$i];
|
||||||
|
if (isset($tokens1[$i - 1])) {
|
||||||
|
$previousToken = $tokens1[$i - 1];
|
||||||
|
} else {
|
||||||
|
$previousToken = null;
|
||||||
|
}
|
||||||
|
if (isset($tokens1[$i + 1])) {
|
||||||
|
$nextToken = $tokens1[$i + 1];
|
||||||
|
} else {
|
||||||
|
$nextToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($token)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($token->getTokenType() != PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE) {
|
||||||
|
$tokens2[] = $token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($previousToken)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! (
|
||||||
|
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
|
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
|
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
|
) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($nextToken)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! (
|
||||||
|
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
|
||||||
|
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
|
||||||
|
($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
|
) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokens2[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_INTERSECTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move tokens to final list, switching infix "-" operators to prefix when appropriate, switching infix "+" operators
|
||||||
|
// to noop when appropriate, identifying operand and infix-operator subtypes, and pulling "@" from function names
|
||||||
|
$this->_tokens = array();
|
||||||
|
|
||||||
|
$tokenCount = count($tokens2);
|
||||||
|
for ($i = 0; $i < $tokenCount; ++$i) {
|
||||||
|
$token = $tokens2[$i];
|
||||||
|
if (isset($tokens2[$i - 1])) {
|
||||||
|
$previousToken = $tokens2[$i - 1];
|
||||||
|
} else {
|
||||||
|
$previousToken = null;
|
||||||
|
}
|
||||||
|
if (isset($tokens2[$i + 1])) {
|
||||||
|
$nextToken = $tokens2[$i + 1];
|
||||||
|
} else {
|
||||||
|
$nextToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($token)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "-") {
|
||||||
|
if ($i == 0) {
|
||||||
|
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
|
||||||
|
} else if (
|
||||||
|
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
|
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
|
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
|
||||||
|
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
|
) {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
|
||||||
|
} else {
|
||||||
|
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_tokens[] = $token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "+") {
|
||||||
|
if ($i == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (
|
||||||
|
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
|
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
|
||||||
|
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
|
||||||
|
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
|
||||||
|
) {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_tokens[] = $token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
|
||||||
|
if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
|
||||||
|
} else if ($token->getValue() == "&") {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_CONCATENATION);
|
||||||
|
} else {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_tokens[] = $token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
|
||||||
|
if (!is_numeric($token->getValue())) {
|
||||||
|
if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
|
||||||
|
} else {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_RANGE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_tokens[] = $token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
|
||||||
|
if (strlen($token->getValue() > 0)) {
|
||||||
|
if (substr($token->getValue(), 0, 1) == "@") {
|
||||||
|
$token->setValue(substr($token->getValue(), 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_tokens[] = $token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,176 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
PARTLY BASED ON:
|
||||||
|
Copyright (c) 2007 E. W. Bachtal, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||||
|
portions of the Software.
|
||||||
|
|
||||||
|
The software is provided "as is", without warranty of any kind, express or implied, including but not
|
||||||
|
limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In
|
||||||
|
no event shall the authors or copyright holders be liable for any claim, damages or other liability,
|
||||||
|
whether in an action of contract, tort or otherwise, arising from, out of or in connection with the
|
||||||
|
software or the use or other dealings in the software.
|
||||||
|
|
||||||
|
http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html
|
||||||
|
http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Calculation_FormulaToken
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Calculation_FormulaToken {
|
||||||
|
/* Token types */
|
||||||
|
const TOKEN_TYPE_NOOP = 'Noop';
|
||||||
|
const TOKEN_TYPE_OPERAND = 'Operand';
|
||||||
|
const TOKEN_TYPE_FUNCTION = 'Function';
|
||||||
|
const TOKEN_TYPE_SUBEXPRESSION = 'Subexpression';
|
||||||
|
const TOKEN_TYPE_ARGUMENT = 'Argument';
|
||||||
|
const TOKEN_TYPE_OPERATORPREFIX = 'OperatorPrefix';
|
||||||
|
const TOKEN_TYPE_OPERATORINFIX = 'OperatorInfix';
|
||||||
|
const TOKEN_TYPE_OPERATORPOSTFIX = 'OperatorPostfix';
|
||||||
|
const TOKEN_TYPE_WHITESPACE = 'Whitespace';
|
||||||
|
const TOKEN_TYPE_UNKNOWN = 'Unknown';
|
||||||
|
|
||||||
|
/* Token subtypes */
|
||||||
|
const TOKEN_SUBTYPE_NOTHING = 'Nothing';
|
||||||
|
const TOKEN_SUBTYPE_START = 'Start';
|
||||||
|
const TOKEN_SUBTYPE_STOP = 'Stop';
|
||||||
|
const TOKEN_SUBTYPE_TEXT = 'Text';
|
||||||
|
const TOKEN_SUBTYPE_NUMBER = 'Number';
|
||||||
|
const TOKEN_SUBTYPE_LOGICAL = 'Logical';
|
||||||
|
const TOKEN_SUBTYPE_ERROR = 'Error';
|
||||||
|
const TOKEN_SUBTYPE_RANGE = 'Range';
|
||||||
|
const TOKEN_SUBTYPE_MATH = 'Math';
|
||||||
|
const TOKEN_SUBTYPE_CONCATENATION = 'Concatenation';
|
||||||
|
const TOKEN_SUBTYPE_INTERSECTION = 'Intersection';
|
||||||
|
const TOKEN_SUBTYPE_UNION = 'Union';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token Type (represented by TOKEN_TYPE_*)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_tokenType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token SubType (represented by TOKEN_SUBTYPE_*)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_tokenSubType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Calculation_FormulaToken
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @param string $pTokenType Token type (represented by TOKEN_TYPE_*)
|
||||||
|
* @param string $pTokenSubType Token Subtype (represented by TOKEN_SUBTYPE_*)
|
||||||
|
*/
|
||||||
|
public function __construct($pValue, $pTokenType = PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN, $pTokenSubType = PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING)
|
||||||
|
{
|
||||||
|
// Initialise values
|
||||||
|
$this->_value = $pValue;
|
||||||
|
$this->_tokenType = $pTokenType;
|
||||||
|
$this->_tokenSubType = $pTokenSubType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Value
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getValue() {
|
||||||
|
return $this->_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Value
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setValue($value) {
|
||||||
|
$this->_value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Token Type (represented by TOKEN_TYPE_*)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTokenType() {
|
||||||
|
return $this->_tokenType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Token Type
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setTokenType($value = PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN) {
|
||||||
|
$this->_tokenType = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Token SubType (represented by TOKEN_SUBTYPE_*)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTokenSubType() {
|
||||||
|
return $this->_tokenSubType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Token SubType
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setTokenSubType($value = PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
|
||||||
|
$this->_tokenSubType = $value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Calculation_Function
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Calculation
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Calculation_Function {
|
||||||
|
/* Function categories */
|
||||||
|
const CATEGORY_CUBE = 'Cube';
|
||||||
|
const CATEGORY_DATABASE = 'Database';
|
||||||
|
const CATEGORY_DATE_AND_TIME = 'Date and Time';
|
||||||
|
const CATEGORY_ENGINEERING = 'Engineering';
|
||||||
|
const CATEGORY_FINANCIAL = 'Financial';
|
||||||
|
const CATEGORY_INFORMATION = 'Information';
|
||||||
|
const CATEGORY_LOGICAL = 'Logical';
|
||||||
|
const CATEGORY_LOOKUP_AND_REFERENCE = 'Lookup and Reference';
|
||||||
|
const CATEGORY_MATH_AND_TRIG = 'Math and Trig';
|
||||||
|
const CATEGORY_STATISTICAL = 'Statistical';
|
||||||
|
const CATEGORY_TEXT_AND_DATA = 'Text and Data';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Category (represented by CATEGORY_*)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excel name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_excelName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_phpExcelName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Calculation_Function
|
||||||
|
*
|
||||||
|
* @param string $pCategory Category (represented by CATEGORY_*)
|
||||||
|
* @param string $pExcelName Excel function name
|
||||||
|
* @param string $pPHPExcelName PHPExcel function mapping
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct($pCategory = null, $pExcelName = null, $pPHPExcelName = null)
|
||||||
|
{
|
||||||
|
if (!is_null($pCategory) && !is_null($pExcelName) && !is_null($pPHPExcelName)) {
|
||||||
|
// Initialise values
|
||||||
|
$this->_category = $pCategory;
|
||||||
|
$this->_excelName = $pExcelName;
|
||||||
|
$this->_phpExcelName = $pPHPExcelName;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Invalid parameters passed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Category (represented by CATEGORY_*)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCategory() {
|
||||||
|
return $this->_category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Category (represented by CATEGORY_*)
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function setCategory($value = null) {
|
||||||
|
if (!is_null($value)) {
|
||||||
|
$this->_category = $value;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Invalid parameter passed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Excel name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getExcelName() {
|
||||||
|
return $this->_excelName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Excel name
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setExcelName($value) {
|
||||||
|
$this->_excelName = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get PHPExcel name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPHPExcelName() {
|
||||||
|
return $this->_phpExcelName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set PHPExcel name
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function setPHPExcelName($value) {
|
||||||
|
$this->_phpExcelName = $value;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,351 @@
|
||||||
|
ABS
|
||||||
|
ACCRINT
|
||||||
|
ACCRINTM
|
||||||
|
ACOS
|
||||||
|
ACOSH
|
||||||
|
ADDRESS
|
||||||
|
AMORDEGRC
|
||||||
|
AMORLINC
|
||||||
|
AND
|
||||||
|
AREAS
|
||||||
|
ASC
|
||||||
|
ASIN
|
||||||
|
ASINH
|
||||||
|
ATAN
|
||||||
|
ATAN2
|
||||||
|
ATANH
|
||||||
|
AVEDEV
|
||||||
|
AVERAGE
|
||||||
|
AVERAGEA
|
||||||
|
AVERAGEIF
|
||||||
|
AVERAGEIFS
|
||||||
|
BAHTTEXT
|
||||||
|
BESSELI
|
||||||
|
BESSELJ
|
||||||
|
BESSELK
|
||||||
|
BESSELY
|
||||||
|
BETADIST
|
||||||
|
BETAINV
|
||||||
|
BIN2DEC
|
||||||
|
BIN2HEX
|
||||||
|
BIN2OCT
|
||||||
|
BINOMDIST
|
||||||
|
CEILING
|
||||||
|
CELL
|
||||||
|
CHAR
|
||||||
|
CHIDIST
|
||||||
|
CHIINV
|
||||||
|
CHITEST
|
||||||
|
CHOOSE
|
||||||
|
CLEAN
|
||||||
|
CODE
|
||||||
|
COLUMN
|
||||||
|
COLUMNS
|
||||||
|
COMBIN
|
||||||
|
COMPLEX
|
||||||
|
CONCATENATE
|
||||||
|
CONFIDENCE
|
||||||
|
CONVERT
|
||||||
|
CORREL
|
||||||
|
COS
|
||||||
|
COSH
|
||||||
|
COUNT
|
||||||
|
COUNTA
|
||||||
|
COUNTBLANK
|
||||||
|
COUNTIF
|
||||||
|
COUNTIFS
|
||||||
|
COUPDAYBS
|
||||||
|
COUPDAYBS
|
||||||
|
COUPDAYSNC
|
||||||
|
COUPNCD
|
||||||
|
COUPNUM
|
||||||
|
COUPPCD
|
||||||
|
COVAR
|
||||||
|
CRITBINOM
|
||||||
|
CUBEKPIMEMBER
|
||||||
|
CUBEMEMBER
|
||||||
|
CUBEMEMBERPROPERTY
|
||||||
|
CUBERANKEDMEMBER
|
||||||
|
CUBESET
|
||||||
|
CUBESETCOUNT
|
||||||
|
CUBEVALUE
|
||||||
|
CUMIPMT
|
||||||
|
CUMPRINC
|
||||||
|
DATE
|
||||||
|
DATEDIF
|
||||||
|
DATEVALUE
|
||||||
|
DAVERAGE
|
||||||
|
DAY
|
||||||
|
DAYS360
|
||||||
|
DB
|
||||||
|
DCOUNT
|
||||||
|
DCOUNTA
|
||||||
|
DDB
|
||||||
|
DEC2BIN
|
||||||
|
DEC2HEX
|
||||||
|
DEC2OCT
|
||||||
|
DEGREES
|
||||||
|
DELTA
|
||||||
|
DEVSQ
|
||||||
|
DGET
|
||||||
|
DISC
|
||||||
|
DMAX
|
||||||
|
DMIN
|
||||||
|
DOLLAR
|
||||||
|
DOLLARDE
|
||||||
|
DOLLARFR
|
||||||
|
DPRODUCT
|
||||||
|
DSTDEV
|
||||||
|
DSTDEVP
|
||||||
|
DSUM
|
||||||
|
DURATION
|
||||||
|
DVAR
|
||||||
|
DVARP
|
||||||
|
EDATE
|
||||||
|
EFFECT
|
||||||
|
EOMONTH
|
||||||
|
ERF
|
||||||
|
ERFC
|
||||||
|
ERROR.TYPE
|
||||||
|
EVEN
|
||||||
|
EXACT
|
||||||
|
EXP
|
||||||
|
EXPONDIST
|
||||||
|
FACT
|
||||||
|
FACTDOUBLE
|
||||||
|
FALSE
|
||||||
|
FDIST
|
||||||
|
FIND
|
||||||
|
FINDB
|
||||||
|
FINV
|
||||||
|
FISHER
|
||||||
|
FISHERINV
|
||||||
|
FIXED
|
||||||
|
FLOOR
|
||||||
|
FORECAST
|
||||||
|
FREQUENCY
|
||||||
|
FTEST
|
||||||
|
FV
|
||||||
|
FVSCHEDULE
|
||||||
|
GAMAMDIST
|
||||||
|
GAMMAINV
|
||||||
|
GAMMALN
|
||||||
|
GCD
|
||||||
|
GEOMEAN
|
||||||
|
GESTEP
|
||||||
|
GETPIVOTDATA
|
||||||
|
GROWTH
|
||||||
|
HARMEAN
|
||||||
|
HEX2BIN
|
||||||
|
HEX2OCT
|
||||||
|
HLOOKUP
|
||||||
|
HOUR
|
||||||
|
HYPERLINK
|
||||||
|
HYPGEOMDIST
|
||||||
|
IF
|
||||||
|
IFERROR
|
||||||
|
IMABS
|
||||||
|
IMAGINARY
|
||||||
|
IMARGUMENT
|
||||||
|
IMCONJUGATE
|
||||||
|
IMCOS
|
||||||
|
IMEXP
|
||||||
|
IMLN
|
||||||
|
IMLOG10
|
||||||
|
IMLOG2
|
||||||
|
IMPOWER
|
||||||
|
IMPRODUCT
|
||||||
|
IMREAL
|
||||||
|
IMSIN
|
||||||
|
IMSQRT
|
||||||
|
IMSUB
|
||||||
|
IMSUM
|
||||||
|
INDEX
|
||||||
|
INDIRECT
|
||||||
|
INFO
|
||||||
|
INT
|
||||||
|
INTERCEPT
|
||||||
|
INTRATE
|
||||||
|
IPMT
|
||||||
|
IRR
|
||||||
|
ISBLANK
|
||||||
|
ISERR
|
||||||
|
ISERROR
|
||||||
|
ISEVEN
|
||||||
|
ISLOGICAL
|
||||||
|
ISNA
|
||||||
|
ISNONTEXT
|
||||||
|
ISNUMBER
|
||||||
|
ISODD
|
||||||
|
ISPMT
|
||||||
|
ISREF
|
||||||
|
ISTEXT
|
||||||
|
JIS
|
||||||
|
KURT
|
||||||
|
LARGE
|
||||||
|
LCM
|
||||||
|
LEFT
|
||||||
|
LEFTB
|
||||||
|
LEN
|
||||||
|
LENB
|
||||||
|
LINEST
|
||||||
|
LN
|
||||||
|
LOG
|
||||||
|
LOG10
|
||||||
|
LOGEST
|
||||||
|
LOGINV
|
||||||
|
LOGNORMDIST
|
||||||
|
LOOKUP
|
||||||
|
LOWER
|
||||||
|
MATCH
|
||||||
|
MAX
|
||||||
|
MAXA
|
||||||
|
MDETERM
|
||||||
|
MDURATION
|
||||||
|
MEDIAN
|
||||||
|
MID
|
||||||
|
MIDB
|
||||||
|
MIN
|
||||||
|
MINA
|
||||||
|
MINUTE
|
||||||
|
MINVERSE
|
||||||
|
MIRR
|
||||||
|
MMULT
|
||||||
|
MOD
|
||||||
|
MODE
|
||||||
|
MONTH
|
||||||
|
MROUND
|
||||||
|
MULTINOMIAL
|
||||||
|
N
|
||||||
|
NA
|
||||||
|
NEGBINOMDIST
|
||||||
|
NETWORKDAYS
|
||||||
|
NOMINAL
|
||||||
|
NORMDIST
|
||||||
|
NORMINV
|
||||||
|
NORMSDIST
|
||||||
|
NORMSINV
|
||||||
|
NOT
|
||||||
|
NOW
|
||||||
|
NPER
|
||||||
|
NPV
|
||||||
|
OCT2BIN
|
||||||
|
OCT2DEC
|
||||||
|
OCT2HEX
|
||||||
|
ODD
|
||||||
|
ODDFPRICE
|
||||||
|
ODDFYIELD
|
||||||
|
ODDLPRICE
|
||||||
|
ODDLYIELD
|
||||||
|
OFFSET
|
||||||
|
OR
|
||||||
|
PEARSON
|
||||||
|
PERCENTILE
|
||||||
|
PERCENTRANK
|
||||||
|
PERMUT
|
||||||
|
PHONETIC
|
||||||
|
PI
|
||||||
|
PMT
|
||||||
|
POISSON
|
||||||
|
POWER
|
||||||
|
PPMT
|
||||||
|
PRICE
|
||||||
|
PRICEDISC
|
||||||
|
PRICEMAT
|
||||||
|
PROB
|
||||||
|
PRODUCT
|
||||||
|
PROPER
|
||||||
|
PV
|
||||||
|
QUARTILE
|
||||||
|
QUOTIENT
|
||||||
|
RADIANS
|
||||||
|
RAND
|
||||||
|
RANDBETWEEN
|
||||||
|
RANK
|
||||||
|
RATE
|
||||||
|
RECEIVED
|
||||||
|
REPLACE
|
||||||
|
REPLACEB
|
||||||
|
REPT
|
||||||
|
RIGHT
|
||||||
|
RIGHTB
|
||||||
|
ROMAN
|
||||||
|
ROUND
|
||||||
|
ROUNDDOWN
|
||||||
|
ROUNDUP
|
||||||
|
ROW
|
||||||
|
ROWS
|
||||||
|
RSQ
|
||||||
|
RTD
|
||||||
|
SEARCH
|
||||||
|
SEARCHB
|
||||||
|
SECOND
|
||||||
|
SERIESSUM
|
||||||
|
SIGN
|
||||||
|
SIN
|
||||||
|
SINH
|
||||||
|
SKEW
|
||||||
|
SLN
|
||||||
|
SLOPE
|
||||||
|
SMALL
|
||||||
|
SQRT
|
||||||
|
SQRTPI
|
||||||
|
STANDARDIZE
|
||||||
|
STDEV
|
||||||
|
STDEVA
|
||||||
|
STDEVP
|
||||||
|
STDEVPA
|
||||||
|
STEYX
|
||||||
|
SUBSTITUTE
|
||||||
|
SUBTOTAL
|
||||||
|
SUM
|
||||||
|
SUMIF
|
||||||
|
SUMIFS
|
||||||
|
SUMPRODUCT
|
||||||
|
SUMSQ
|
||||||
|
SUMX2MY2
|
||||||
|
SUMX2PY2
|
||||||
|
SUMXMY2
|
||||||
|
SYD
|
||||||
|
T
|
||||||
|
TAN
|
||||||
|
TANH
|
||||||
|
TBILLEQ
|
||||||
|
TBILLPRICE
|
||||||
|
TBILLYIELD
|
||||||
|
TDIST
|
||||||
|
TEXT
|
||||||
|
TIME
|
||||||
|
TIMEVALUE
|
||||||
|
TINV
|
||||||
|
TODAY
|
||||||
|
TRANSPOSE
|
||||||
|
TREND
|
||||||
|
TRIM
|
||||||
|
TRIMMEAN
|
||||||
|
TRUE
|
||||||
|
TRUNC
|
||||||
|
TTEST
|
||||||
|
TYPE
|
||||||
|
UPPER
|
||||||
|
USDOLLAR
|
||||||
|
VALUE
|
||||||
|
VAR
|
||||||
|
VARA
|
||||||
|
VARP
|
||||||
|
VARPA
|
||||||
|
VDB
|
||||||
|
VERSION
|
||||||
|
VLOOKUP
|
||||||
|
WEEKDAY
|
||||||
|
WEEKNUM
|
||||||
|
WEIBULL
|
||||||
|
WORKDAY
|
||||||
|
XIRR
|
||||||
|
XNPV
|
||||||
|
YEAR
|
||||||
|
YEARFRAC
|
||||||
|
YIELD
|
||||||
|
YIELDDISC
|
||||||
|
YIELDMAT
|
||||||
|
ZTEST
|
|
@ -0,0 +1,834 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Cell
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Cell
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Value binder to use
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Cell_IValueBinder
|
||||||
|
*/
|
||||||
|
private static $_valueBinder = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column of the cell
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_column;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Row of the cell
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_row;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value of the cell
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $_value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculated value of the cell (used for caching)
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $_calculatedValue = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of the cell data
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_dataType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent worksheet
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
private $_parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index to cellXf
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_xfIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attributes of the formula
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private $_formulaAttributes;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notification to the cache controller
|
||||||
|
* @return void
|
||||||
|
**/
|
||||||
|
public function notifyCacheController() {
|
||||||
|
$this->_parent->getCellCacheController()->updateCacheData($this);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function detach() {
|
||||||
|
$this->_parent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attach($parent) {
|
||||||
|
$this->_parent = $parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Cell
|
||||||
|
*
|
||||||
|
* @param string $pColumn
|
||||||
|
* @param int $pRow
|
||||||
|
* @param mixed $pValue
|
||||||
|
* @param string $pDataType
|
||||||
|
* @param PHPExcel_Worksheet $pSheet
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct($pColumn = 'A', $pRow = 1, $pValue = null, $pDataType = null, PHPExcel_Worksheet $pSheet = null)
|
||||||
|
{
|
||||||
|
// Initialise cell coordinate
|
||||||
|
$this->_column = strtoupper($pColumn);
|
||||||
|
$this->_row = $pRow;
|
||||||
|
|
||||||
|
// Initialise cell value
|
||||||
|
$this->_value = $pValue;
|
||||||
|
|
||||||
|
// Set worksheet
|
||||||
|
$this->_parent = $pSheet;
|
||||||
|
|
||||||
|
// Set datatype?
|
||||||
|
if (!is_null($pDataType)) {
|
||||||
|
$this->_dataType = $pDataType;
|
||||||
|
} else {
|
||||||
|
if (!self::getValueBinder()->bindValue($this, $pValue)) {
|
||||||
|
throw new Exception("Value could not be bound to cell.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default index to cellXf
|
||||||
|
$this->_xfIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell coordinate column
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getColumn()
|
||||||
|
{
|
||||||
|
return $this->_column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell coordinate row
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getRow()
|
||||||
|
{
|
||||||
|
return $this->_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell coordinate
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCoordinate()
|
||||||
|
{
|
||||||
|
return $this->_column . $this->_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell value
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getValue()
|
||||||
|
{
|
||||||
|
return $this->_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cell value
|
||||||
|
*
|
||||||
|
* This clears the cell formula.
|
||||||
|
*
|
||||||
|
* @param mixed $pValue Value
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
public function setValue($pValue = null)
|
||||||
|
{
|
||||||
|
if (!self::getValueBinder()->bindValue($this, $pValue)) {
|
||||||
|
throw new Exception("Value could not be bound to cell.");
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cell value (with explicit data type given)
|
||||||
|
*
|
||||||
|
* @param mixed $pValue Value
|
||||||
|
* @param string $pDataType Explicit data type
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function setValueExplicit($pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
|
||||||
|
{
|
||||||
|
// set the value according to data type
|
||||||
|
switch ($pDataType) {
|
||||||
|
case PHPExcel_Cell_DataType::TYPE_STRING:
|
||||||
|
case PHPExcel_Cell_DataType::TYPE_NULL:
|
||||||
|
case PHPExcel_Cell_DataType::TYPE_INLINE:
|
||||||
|
$this->_value = PHPExcel_Cell_DataType::checkString($pValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHPExcel_Cell_DataType::TYPE_NUMERIC:
|
||||||
|
$this->_value = (float)$pValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHPExcel_Cell_DataType::TYPE_FORMULA:
|
||||||
|
$this->_value = (string)$pValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHPExcel_Cell_DataType::TYPE_BOOL:
|
||||||
|
$this->_value = (bool)$pValue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHPExcel_Cell_DataType::TYPE_ERROR:
|
||||||
|
$this->_value = PHPExcel_Cell_DataType::checkErrorCode($pValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception('Invalid datatype: ' . $pDataType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the datatype
|
||||||
|
$this->_dataType = $pDataType;
|
||||||
|
|
||||||
|
return $this->notifyCacheController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get calculated cell value
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getCalculatedValue($resetLog=true)
|
||||||
|
{
|
||||||
|
// echo 'Cell '.$this->getCoordinate().' value is a '.$this->_dataType.' with a value of '.$this->getValue().'<br />';
|
||||||
|
if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) {
|
||||||
|
try {
|
||||||
|
// echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value<br />';
|
||||||
|
$result = PHPExcel_Calculation::getInstance()->calculateCellValue($this,$resetLog);
|
||||||
|
// echo $this->getCoordinate().' calculation result is '.$result.'<br />';
|
||||||
|
} catch ( Exception $ex ) {
|
||||||
|
// echo 'Calculation Exception: '.$ex->getMessage().'<br />';
|
||||||
|
$result = '#N/A';
|
||||||
|
throw(new Exception($this->getParent()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result === '#Not Yet Implemented') {
|
||||||
|
// echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().'<br />';
|
||||||
|
return $this->_calculatedValue; // Fallback if calculation engine does not support the formula.
|
||||||
|
}
|
||||||
|
// echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().'<br />';
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($this->_value)) {
|
||||||
|
// echo 'Cell '.$this->getCoordinate().' has no value, formula or otherwise<br />';
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// echo 'Cell value for '.$this->getCoordinate().' is not a formula: Returning data value of '.$this->_value.'<br />';
|
||||||
|
return $this->_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set calculated value (used for caching)
|
||||||
|
*
|
||||||
|
* @param mixed $pValue Value
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
public function setCalculatedValue($pValue = null)
|
||||||
|
{
|
||||||
|
if (!is_null($pValue)) {
|
||||||
|
$this->_calculatedValue = $pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->notifyCacheController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get old calculated value (cached)
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getOldCalculatedValue()
|
||||||
|
{
|
||||||
|
return $this->_calculatedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cell data type
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDataType()
|
||||||
|
{
|
||||||
|
return $this->_dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cell data type
|
||||||
|
*
|
||||||
|
* @param string $pDataType
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
public function setDataType($pDataType = PHPExcel_Cell_DataType::TYPE_STRING)
|
||||||
|
{
|
||||||
|
$this->_dataType = $pDataType;
|
||||||
|
|
||||||
|
return $this->notifyCacheController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has Data validation?
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function hasDataValidation()
|
||||||
|
{
|
||||||
|
if (!isset($this->_parent)) {
|
||||||
|
throw new Exception('Cannot check for data validation when cell is not bound to a worksheet');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_parent->dataValidationExists($this->getCoordinate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Data validation
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function getDataValidation()
|
||||||
|
{
|
||||||
|
if (!isset($this->_parent)) {
|
||||||
|
throw new Exception('Cannot get data validation for cell that is not bound to a worksheet');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_parent->getDataValidation($this->getCoordinate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Data validation
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell_DataValidation $pDataValidation
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
public function setDataValidation(PHPExcel_Cell_DataValidation $pDataValidation = null)
|
||||||
|
{
|
||||||
|
if (!isset($this->_parent)) {
|
||||||
|
throw new Exception('Cannot set data validation for cell that is not bound to a worksheet');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_parent->setDataValidation($this->getCoordinate(), $pDataValidation);
|
||||||
|
|
||||||
|
return $this->notifyCacheController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has Hyperlink
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function hasHyperlink()
|
||||||
|
{
|
||||||
|
if (!isset($this->_parent)) {
|
||||||
|
throw new Exception('Cannot check for hyperlink when cell is not bound to a worksheet');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_parent->hyperlinkExists($this->getCoordinate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Hyperlink
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell_Hyperlink
|
||||||
|
*/
|
||||||
|
public function getHyperlink()
|
||||||
|
{
|
||||||
|
if (!isset($this->_parent)) {
|
||||||
|
throw new Exception('Cannot get hyperlink for cell that is not bound to a worksheet');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_parent->getHyperlink($this->getCoordinate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Hyperlink
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell_Hyperlink $pHyperlink
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
public function setHyperlink(PHPExcel_Cell_Hyperlink $pHyperlink = null)
|
||||||
|
{
|
||||||
|
if (!isset($this->_parent)) {
|
||||||
|
throw new Exception('Cannot set hyperlink for cell that is not bound to a worksheet');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_parent->setHyperlink($this->getCoordinate(), $pHyperlink);
|
||||||
|
|
||||||
|
return $this->notifyCacheController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parent
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
public function getParent() {
|
||||||
|
return $this->_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-bind parent
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Worksheet $parent
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
public function rebindParent(PHPExcel_Worksheet $parent) {
|
||||||
|
$this->_parent = $parent;
|
||||||
|
|
||||||
|
return $this->notifyCacheController();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is cell in a specific range?
|
||||||
|
*
|
||||||
|
* @param string $pRange Cell range (e.g. A1:A1)
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isInRange($pRange = 'A1:A1')
|
||||||
|
{
|
||||||
|
list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange);
|
||||||
|
|
||||||
|
// Translate properties
|
||||||
|
$myColumn = PHPExcel_Cell::columnIndexFromString($this->getColumn()) - 1;
|
||||||
|
$myRow = $this->getRow();
|
||||||
|
|
||||||
|
// Verify if cell is in range
|
||||||
|
return (($rangeStart[0] <= $myColumn) && ($rangeEnd[0] >= $myColumn) &&
|
||||||
|
($rangeStart[1] <= $myRow) && ($rangeEnd[1] >= $myRow)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coordinate from string
|
||||||
|
*
|
||||||
|
* @param string $pCoordinateString
|
||||||
|
* @return array Array containing column and row (indexes 0 and 1)
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function coordinateFromString($pCoordinateString = 'A1')
|
||||||
|
{
|
||||||
|
if (strpos($pCoordinateString,':') !== false) {
|
||||||
|
throw new Exception('Cell coordinate string can not be a range of cells.');
|
||||||
|
} else if ($pCoordinateString == '') {
|
||||||
|
throw new Exception('Cell coordinate can not be zero-length string.');
|
||||||
|
} else if (preg_match("/([$]?[A-Z]+)([$]?\d+)/", $pCoordinateString, $matches)) {
|
||||||
|
list(, $column, $row) = $matches;
|
||||||
|
return array($column, $row);
|
||||||
|
} else {
|
||||||
|
throw new Exception('Invalid cell coordinate.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make string coordinate absolute
|
||||||
|
*
|
||||||
|
* @param string $pCoordinateString
|
||||||
|
* @return string Absolute coordinate
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function absoluteCoordinate($pCoordinateString = 'A1')
|
||||||
|
{
|
||||||
|
if (strpos($pCoordinateString,':') === false && strpos($pCoordinateString,',') === false) {
|
||||||
|
// Create absolute coordinate
|
||||||
|
list($column, $row) = PHPExcel_Cell::coordinateFromString($pCoordinateString);
|
||||||
|
return '$' . $column . '$' . $row;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Coordinate string should not be a cell range.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split range into coordinate strings
|
||||||
|
*
|
||||||
|
* @param string $pRange
|
||||||
|
* @return array Array containg one or more arrays containing one or two coordinate strings
|
||||||
|
*/
|
||||||
|
public static function splitRange($pRange = 'A1:A1')
|
||||||
|
{
|
||||||
|
$exploded = explode(',', $pRange);
|
||||||
|
for ($i = 0; $i < count($exploded); ++$i) {
|
||||||
|
$exploded[$i] = explode(':', $exploded[$i]);
|
||||||
|
}
|
||||||
|
return $exploded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build range from coordinate strings
|
||||||
|
*
|
||||||
|
* @param array $pRange Array containg one or more arrays containing one or two coordinate strings
|
||||||
|
* @return string String representation of $pRange
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function buildRange($pRange)
|
||||||
|
{
|
||||||
|
// Verify range
|
||||||
|
if (!is_array($pRange) || count($pRange) == 0 || !is_array($pRange[0])) {
|
||||||
|
throw new Exception('Range does not contain any information.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build range
|
||||||
|
$imploded = array();
|
||||||
|
for ($i = 0; $i < count($pRange); ++$i) {
|
||||||
|
$pRange[$i] = implode(':', $pRange[$i]);
|
||||||
|
}
|
||||||
|
$imploded = implode(',', $pRange);
|
||||||
|
|
||||||
|
return $imploded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate range boundaries
|
||||||
|
*
|
||||||
|
* @param string $pRange Cell range (e.g. A1:A1)
|
||||||
|
* @return array Range coordinates (Start Cell, End Cell) where Start Cell and End Cell are arrays (Column Number, Row Number)
|
||||||
|
*/
|
||||||
|
public static function rangeBoundaries($pRange = 'A1:A1')
|
||||||
|
{
|
||||||
|
// Uppercase coordinate
|
||||||
|
$pRange = strtoupper($pRange);
|
||||||
|
|
||||||
|
// Extract range
|
||||||
|
if (strpos($pRange, ':') === false) {
|
||||||
|
$rangeA = $rangeB = $pRange;
|
||||||
|
} else {
|
||||||
|
list($rangeA, $rangeB) = explode(':', $pRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate range outer borders
|
||||||
|
$rangeStart = PHPExcel_Cell::coordinateFromString($rangeA);
|
||||||
|
$rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB);
|
||||||
|
|
||||||
|
// Translate column into index
|
||||||
|
$rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]);
|
||||||
|
$rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]);
|
||||||
|
|
||||||
|
return array($rangeStart, $rangeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate range dimension
|
||||||
|
*
|
||||||
|
* @param string $pRange Cell range (e.g. A1:A1)
|
||||||
|
* @return array Range dimension (width, height)
|
||||||
|
*/
|
||||||
|
public static function rangeDimension($pRange = 'A1:A1')
|
||||||
|
{
|
||||||
|
// Calculate range outer borders
|
||||||
|
list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange);
|
||||||
|
|
||||||
|
return array( ($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate range boundaries
|
||||||
|
*
|
||||||
|
* @param string $pRange Cell range (e.g. A1:A1)
|
||||||
|
* @return array Range boundaries (staring Column, starting Row, Final Column, Final Row)
|
||||||
|
*/
|
||||||
|
public static function getRangeBoundaries($pRange = 'A1:A1')
|
||||||
|
{
|
||||||
|
// Uppercase coordinate
|
||||||
|
$pRange = strtoupper($pRange);
|
||||||
|
|
||||||
|
// Extract range
|
||||||
|
if (strpos($pRange, ':') === false) {
|
||||||
|
$rangeA = $pRange;
|
||||||
|
$rangeB = $pRange;
|
||||||
|
} else {
|
||||||
|
list($rangeA, $rangeB) = explode(':', $pRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array( self::coordinateFromString($rangeA), self::coordinateFromString($rangeB));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column index from string
|
||||||
|
*
|
||||||
|
* @param string $pString
|
||||||
|
* @return int Column index (base 1 !!!)
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function columnIndexFromString($pString = 'A')
|
||||||
|
{
|
||||||
|
static $lookup = array(
|
||||||
|
'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8, 'I' => 9, 'J' => 10, 'K' => 11, 'L' => 12, 'M' => 13,
|
||||||
|
'N' => 14, 'O' => 15, 'P' => 16, 'Q' => 17, 'R' => 18, 'S' => 19, 'T' => 20, 'U' => 21, 'V' => 22, 'W' => 23, 'X' => 24, 'Y' => 25, 'Z' => 26
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($lookup[$pString]))
|
||||||
|
return $lookup[$pString];
|
||||||
|
|
||||||
|
// Convert to uppercase
|
||||||
|
$pString = strtoupper($pString);
|
||||||
|
|
||||||
|
$strLen = strlen($pString);
|
||||||
|
// Convert column to integer
|
||||||
|
if ($strLen == 1) {
|
||||||
|
return (ord($pString{0}) - 64);
|
||||||
|
} elseif ($strLen == 2) {
|
||||||
|
return $result = ((1 + (ord($pString{0}) - 65)) * 26) + (ord($pString{1}) - 64);
|
||||||
|
} elseif ($strLen == 3) {
|
||||||
|
return ((1 + (ord($pString{0}) - 65)) * 676) + ((1 + (ord($pString{1}) - 65)) * 26) + (ord($pString{2}) - 64);
|
||||||
|
} else {
|
||||||
|
throw new Exception("Column string index can not be " . ($strLen != 0 ? "longer than 3 characters" : "empty") . ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String from columnindex
|
||||||
|
*
|
||||||
|
* @param int $pColumnIndex Column index (base 0 !!!)
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function stringFromColumnIndex($pColumnIndex = 0)
|
||||||
|
{
|
||||||
|
// Determine column string
|
||||||
|
if ($pColumnIndex < 26) {
|
||||||
|
return chr(65 + $pColumnIndex);
|
||||||
|
}
|
||||||
|
return PHPExcel_Cell::stringFromColumnIndex((int)($pColumnIndex / 26) -1).chr(65 + $pColumnIndex%26) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract all cell references in range
|
||||||
|
*
|
||||||
|
* @param string $pRange Range (e.g. A1 or A1:A10 or A1:A10 A100:A1000)
|
||||||
|
* @return array Array containing single cell references
|
||||||
|
*/
|
||||||
|
public static function extractAllCellReferencesInRange($pRange = 'A1') {
|
||||||
|
// Returnvalue
|
||||||
|
$returnValue = array();
|
||||||
|
|
||||||
|
// Explode spaces
|
||||||
|
$aExplodeSpaces = explode(' ', str_replace('$', '', strtoupper($pRange)));
|
||||||
|
foreach ($aExplodeSpaces as $explodedSpaces) {
|
||||||
|
// Single cell?
|
||||||
|
if (strpos($explodedSpaces,':') === false && strpos($explodedSpaces,',') === false) {
|
||||||
|
$col = 'A';
|
||||||
|
$row = 1;
|
||||||
|
list($col, $row) = PHPExcel_Cell::coordinateFromString($explodedSpaces);
|
||||||
|
|
||||||
|
if (strlen($col) <= 2) {
|
||||||
|
$returnValue[] = $explodedSpaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range...
|
||||||
|
$range = PHPExcel_Cell::splitRange($explodedSpaces);
|
||||||
|
for ($i = 0; $i < count($range); ++$i) {
|
||||||
|
// Single cell?
|
||||||
|
if (count($range[$i]) == 1) {
|
||||||
|
$col = 'A';
|
||||||
|
$row = 1;
|
||||||
|
list($col, $row) = PHPExcel_Cell::coordinateFromString($range[$i]);
|
||||||
|
|
||||||
|
if (strlen($col) <= 2) {
|
||||||
|
$returnValue[] = $explodedSpaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range...
|
||||||
|
$rangeStart = $rangeEnd = '';
|
||||||
|
$startingCol = $startingRow = $endingCol = $endingRow = 0;
|
||||||
|
|
||||||
|
list($rangeStart, $rangeEnd) = $range[$i];
|
||||||
|
list($startingCol, $startingRow) = PHPExcel_Cell::coordinateFromString($rangeStart);
|
||||||
|
list($endingCol, $endingRow) = PHPExcel_Cell::coordinateFromString($rangeEnd);
|
||||||
|
|
||||||
|
// Conversions...
|
||||||
|
$startingCol = PHPExcel_Cell::columnIndexFromString($startingCol);
|
||||||
|
$endingCol = PHPExcel_Cell::columnIndexFromString($endingCol);
|
||||||
|
|
||||||
|
// Current data
|
||||||
|
$currentCol = --$startingCol;
|
||||||
|
$currentRow = $startingRow;
|
||||||
|
|
||||||
|
// Loop cells
|
||||||
|
while ($currentCol < $endingCol) {
|
||||||
|
$loopColumn = PHPExcel_Cell::stringFromColumnIndex($currentCol);
|
||||||
|
while ($currentRow <= $endingRow) {
|
||||||
|
$returnValue[] = $loopColumn.$currentRow;
|
||||||
|
++$currentRow;
|
||||||
|
}
|
||||||
|
++$currentCol;
|
||||||
|
$currentRow = $startingRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return value
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare 2 cells
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $a Cell a
|
||||||
|
* @param PHPExcel_Cell $a Cell b
|
||||||
|
* @return int Result of comparison (always -1 or 1, never zero!)
|
||||||
|
*/
|
||||||
|
public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b)
|
||||||
|
{
|
||||||
|
if ($a->_row < $b->_row) {
|
||||||
|
return -1;
|
||||||
|
} elseif ($a->_row > $b->_row) {
|
||||||
|
return 1;
|
||||||
|
} elseif (PHPExcel_Cell::columnIndexFromString($a->_column) < PHPExcel_Cell::columnIndexFromString($b->_column)) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value binder to use
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Cell_IValueBinder
|
||||||
|
*/
|
||||||
|
public static function getValueBinder() {
|
||||||
|
if (is_null(self::$_valueBinder)) {
|
||||||
|
self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$_valueBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set value binder to use
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell_IValueBinder $binder
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function setValueBinder(PHPExcel_Cell_IValueBinder $binder = null) {
|
||||||
|
if (is_null($binder)) {
|
||||||
|
throw new Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly.");
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$_valueBinder = $binder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get index to cellXf
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getXfIndex()
|
||||||
|
{
|
||||||
|
return $this->_xfIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set index to cellXf
|
||||||
|
*
|
||||||
|
* @param int $pValue
|
||||||
|
* @return PHPExcel_Cell
|
||||||
|
*/
|
||||||
|
public function setXfIndex($pValue = 0)
|
||||||
|
{
|
||||||
|
$this->_xfIndex = $pValue;
|
||||||
|
|
||||||
|
return $this->notifyCacheController();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function setFormulaAttributes($pAttributes)
|
||||||
|
{
|
||||||
|
$this->_formulaAttributes = $pAttributes;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormulaAttributes()
|
||||||
|
{
|
||||||
|
return $this->_formulaAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Cell_AdvancedValueBinder
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bind value to a cell
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $cell Cell to bind value to
|
||||||
|
* @param mixed $value Value to bind in cell
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function bindValue(PHPExcel_Cell $cell, $value = null)
|
||||||
|
{
|
||||||
|
// sanitize UTF-8 strings
|
||||||
|
if (is_string($value)) {
|
||||||
|
$value = PHPExcel_Shared_String::SanitizeUTF8($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out data type
|
||||||
|
$dataType = parent::dataTypeForValue($value);
|
||||||
|
|
||||||
|
// Style logic - strings
|
||||||
|
if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) {
|
||||||
|
// Check for percentage
|
||||||
|
if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) {
|
||||||
|
// Convert value to number
|
||||||
|
$cell->setValueExplicit( (float)str_replace('%', '', $value) / 100, PHPExcel_Cell_DataType::TYPE_NUMERIC);
|
||||||
|
|
||||||
|
// Set style
|
||||||
|
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for time without seconds e.g. '9:45', '09:45'
|
||||||
|
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) {
|
||||||
|
list($h, $m) = explode(':', $value);
|
||||||
|
$days = $h / 24 + $m / 1440;
|
||||||
|
|
||||||
|
// Convert value to number
|
||||||
|
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC);
|
||||||
|
|
||||||
|
// Set style
|
||||||
|
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for time with seconds '9:45:59', '09:45:59'
|
||||||
|
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) {
|
||||||
|
list($h, $m, $s) = explode(':', $value);
|
||||||
|
$days = $h / 24 + $m / 1440 + $s / 86400;
|
||||||
|
|
||||||
|
// Convert value to number
|
||||||
|
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC);
|
||||||
|
|
||||||
|
// Set style
|
||||||
|
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10'
|
||||||
|
if (($v = PHPExcel_Shared_Date::stringToExcel($value)) !== false) {
|
||||||
|
// Convert value to Excel date
|
||||||
|
$cell->setValueExplicit($v, PHPExcel_Cell_DataType::TYPE_NUMERIC);
|
||||||
|
|
||||||
|
// Set style. Either there is a time part or not. Look for ':'
|
||||||
|
if (strpos($value, ':') !== false) {
|
||||||
|
$formatCode = 'yyyy-mm-dd h:mm';
|
||||||
|
} else {
|
||||||
|
$formatCode = 'yyyy-mm-dd';
|
||||||
|
}
|
||||||
|
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode($formatCode);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for newline character "\n"
|
||||||
|
if (strpos($value, "\n") !== false) {
|
||||||
|
$value = PHPExcel_Shared_String::SanitizeUTF8($value);
|
||||||
|
$cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING);
|
||||||
|
|
||||||
|
// Set style
|
||||||
|
$cell->getParent()->getStyle( $cell->getCoordinate() )->getAlignment()->setWrapText(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not bound yet? Use parent...
|
||||||
|
return parent::bindValue($cell, $value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Cell_DataType
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Cell_DataType
|
||||||
|
{
|
||||||
|
/* Data types */
|
||||||
|
const TYPE_STRING = 's';
|
||||||
|
const TYPE_FORMULA = 'f';
|
||||||
|
const TYPE_NUMERIC = 'n';
|
||||||
|
const TYPE_BOOL = 'b';
|
||||||
|
const TYPE_NULL = 's';
|
||||||
|
const TYPE_INLINE = 'inlineStr';
|
||||||
|
const TYPE_ERROR = 'e';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of error codes
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $_errorCodes = array('#NULL!' => 0, '#DIV/0!' => 1, '#VALUE!' => 2, '#REF!' => 3, '#NAME?' => 4, '#NUM!' => 5, '#N/A' => 6);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of error codes
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getErrorCodes() {
|
||||||
|
return self::$_errorCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataType for value
|
||||||
|
*
|
||||||
|
* @deprecated Replaced by PHPExcel_Cell_IValueBinder infrastructure
|
||||||
|
* @param mixed $pValue
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function dataTypeForValue($pValue = null) {
|
||||||
|
return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a string that it satisfies Excel requirements
|
||||||
|
*
|
||||||
|
* @param mixed Value to sanitize to an Excel string
|
||||||
|
* @return mixed Sanitized value
|
||||||
|
*/
|
||||||
|
public static function checkString($pValue = null)
|
||||||
|
{
|
||||||
|
if ($pValue instanceof PHPExcel_RichText) {
|
||||||
|
// TODO: Sanitize Rich-Text string (max. character count is 32,767)
|
||||||
|
return $pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// string must never be longer than 32,767 characters, truncate if necessary
|
||||||
|
$pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767);
|
||||||
|
|
||||||
|
// we require that newline is represented as "\n" in core, not as "\r\n" or "\r"
|
||||||
|
$pValue = str_replace(array("\r\n", "\r"), "\n", $pValue);
|
||||||
|
|
||||||
|
return $pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a value that it is a valid error code
|
||||||
|
*
|
||||||
|
* @param mixed Value to sanitize to an Excel error code
|
||||||
|
* @return string Sanitized value
|
||||||
|
*/
|
||||||
|
public static function checkErrorCode($pValue = null)
|
||||||
|
{
|
||||||
|
$pValue = (string)$pValue;
|
||||||
|
|
||||||
|
if ( !array_key_exists($pValue, self::$_errorCodes) ) {
|
||||||
|
$pValue = '#NULL!';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,474 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Cell_DataValidation
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Cell_DataValidation
|
||||||
|
{
|
||||||
|
/* Data validation types */
|
||||||
|
const TYPE_NONE = 'none';
|
||||||
|
const TYPE_CUSTOM = 'custom';
|
||||||
|
const TYPE_DATE = 'date';
|
||||||
|
const TYPE_DECIMAL = 'decimal';
|
||||||
|
const TYPE_LIST = 'list';
|
||||||
|
const TYPE_TEXTLENGTH = 'textLength';
|
||||||
|
const TYPE_TIME = 'time';
|
||||||
|
const TYPE_WHOLE = 'whole';
|
||||||
|
|
||||||
|
/* Data validation error styles */
|
||||||
|
const STYLE_STOP = 'stop';
|
||||||
|
const STYLE_WARNING = 'warning';
|
||||||
|
const STYLE_INFORMATION = 'information';
|
||||||
|
|
||||||
|
/* Data validation operators */
|
||||||
|
const OPERATOR_BETWEEN = 'between';
|
||||||
|
const OPERATOR_EQUAL = 'equal';
|
||||||
|
const OPERATOR_GREATERTHAN = 'greaterThan';
|
||||||
|
const OPERATOR_GREATERTHANOREQUAL = 'greaterThanOrEqual';
|
||||||
|
const OPERATOR_LESSTHAN = 'lessThan';
|
||||||
|
const OPERATOR_LESSTHANOREQUAL = 'lessThanOrEqual';
|
||||||
|
const OPERATOR_NOTBETWEEN = 'notBetween';
|
||||||
|
const OPERATOR_NOTEQUAL = 'notEqual';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formula 1
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_formula1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formula 2
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_formula2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_type = PHPExcel_Cell_DataValidation::TYPE_NONE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error style
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operator
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_operator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow Blank
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_allowBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show DropDown
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_showDropDown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show InputMessage
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_showInputMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show ErrorMessage
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_showErrorMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error title
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_errorTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompt title
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_promptTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompt
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_prompt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Cell_DataValidation
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Initialise member variables
|
||||||
|
$this->_formula1 = '';
|
||||||
|
$this->_formula2 = '';
|
||||||
|
$this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE;
|
||||||
|
$this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP;
|
||||||
|
$this->_operator = '';
|
||||||
|
$this->_allowBlank = false;
|
||||||
|
$this->_showDropDown = false;
|
||||||
|
$this->_showInputMessage = false;
|
||||||
|
$this->_showErrorMessage = false;
|
||||||
|
$this->_errorTitle = '';
|
||||||
|
$this->_error = '';
|
||||||
|
$this->_promptTitle = '';
|
||||||
|
$this->_prompt = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Formula 1
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFormula1() {
|
||||||
|
return $this->_formula1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Formula 1
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setFormula1($value = '') {
|
||||||
|
$this->_formula1 = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Formula 2
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFormula2() {
|
||||||
|
return $this->_formula2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Formula 2
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setFormula2($value = '') {
|
||||||
|
$this->_formula2 = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Type
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return $this->_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Type
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setType($value = PHPExcel_Cell_DataValidation::TYPE_NONE) {
|
||||||
|
$this->_type = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Error style
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getErrorStyle() {
|
||||||
|
return $this->_errorStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Error style
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setErrorStyle($value = PHPExcel_Cell_DataValidation::STYLE_STOP) {
|
||||||
|
$this->_errorStyle = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Operator
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getOperator() {
|
||||||
|
return $this->_operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Operator
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setOperator($value = '') {
|
||||||
|
$this->_operator = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Allow Blank
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getAllowBlank() {
|
||||||
|
return $this->_allowBlank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Allow Blank
|
||||||
|
*
|
||||||
|
* @param boolean $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setAllowBlank($value = false) {
|
||||||
|
$this->_allowBlank = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Show DropDown
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getShowDropDown() {
|
||||||
|
return $this->_showDropDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Show DropDown
|
||||||
|
*
|
||||||
|
* @param boolean $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setShowDropDown($value = false) {
|
||||||
|
$this->_showDropDown = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Show InputMessage
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getShowInputMessage() {
|
||||||
|
return $this->_showInputMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Show InputMessage
|
||||||
|
*
|
||||||
|
* @param boolean $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setShowInputMessage($value = false) {
|
||||||
|
$this->_showInputMessage = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Show ErrorMessage
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getShowErrorMessage() {
|
||||||
|
return $this->_showErrorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Show ErrorMessage
|
||||||
|
*
|
||||||
|
* @param boolean $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setShowErrorMessage($value = false) {
|
||||||
|
$this->_showErrorMessage = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Error title
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getErrorTitle() {
|
||||||
|
return $this->_errorTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Error title
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setErrorTitle($value = '') {
|
||||||
|
$this->_errorTitle = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Error
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getError() {
|
||||||
|
return $this->_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Error
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setError($value = '') {
|
||||||
|
$this->_error = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Prompt title
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPromptTitle() {
|
||||||
|
return $this->_promptTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Prompt title
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setPromptTitle($value = '') {
|
||||||
|
$this->_promptTitle = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Prompt
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPrompt() {
|
||||||
|
return $this->_prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Prompt
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_DataValidation
|
||||||
|
*/
|
||||||
|
public function setPrompt($value = '') {
|
||||||
|
$this->_prompt = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode() {
|
||||||
|
return md5(
|
||||||
|
$this->_formula1
|
||||||
|
. $this->_formula2
|
||||||
|
. $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE
|
||||||
|
. $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP
|
||||||
|
. $this->_operator
|
||||||
|
. ($this->_allowBlank ? 't' : 'f')
|
||||||
|
. ($this->_showDropDown ? 't' : 'f')
|
||||||
|
. ($this->_showInputMessage ? 't' : 'f')
|
||||||
|
. ($this->_showErrorMessage ? 't' : 'f')
|
||||||
|
. $this->_errorTitle
|
||||||
|
. $this->_error
|
||||||
|
. $this->_promptTitle
|
||||||
|
. $this->_prompt
|
||||||
|
. __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,96 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Cell_DefaultValueBinder
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bind value to a cell
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $cell Cell to bind value to
|
||||||
|
* @param mixed $value Value to bind in cell
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function bindValue(PHPExcel_Cell $cell, $value = null)
|
||||||
|
{
|
||||||
|
// sanitize UTF-8 strings
|
||||||
|
if (is_string($value)) {
|
||||||
|
$value = PHPExcel_Shared_String::SanitizeUTF8($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set value explicit
|
||||||
|
$cell->setValueExplicit( $value, PHPExcel_Cell_DataType::dataTypeForValue($value) );
|
||||||
|
|
||||||
|
// Done!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataType for value
|
||||||
|
*
|
||||||
|
* @param mixed $pValue
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function dataTypeForValue($pValue = null) {
|
||||||
|
// Match the value against a few data types
|
||||||
|
if (is_null($pValue)) {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_NULL;
|
||||||
|
|
||||||
|
} elseif ($pValue === '') {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_STRING;
|
||||||
|
|
||||||
|
} elseif ($pValue instanceof PHPExcel_RichText) {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_STRING;
|
||||||
|
|
||||||
|
} elseif ($pValue{0} === '=' && strlen($pValue) > 1) {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_FORMULA;
|
||||||
|
|
||||||
|
} elseif (is_bool($pValue)) {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_BOOL;
|
||||||
|
|
||||||
|
} elseif (is_float($pValue) || is_int($pValue)) {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_NUMERIC;
|
||||||
|
|
||||||
|
} elseif (preg_match('/^\-?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)$/', $pValue)) {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_NUMERIC;
|
||||||
|
|
||||||
|
} elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_ERROR;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return PHPExcel_Cell_DataType::TYPE_STRING;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Cell_Hyperlink
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Cell_Hyperlink
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* URL to link the cell to
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tooltip to display on the hyperlink
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_tooltip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Cell_Hyperlink
|
||||||
|
*
|
||||||
|
* @param string $pUrl Url to link the cell to
|
||||||
|
* @param string $pTooltip Tooltip to display on the hyperlink
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct($pUrl = '', $pTooltip = '')
|
||||||
|
{
|
||||||
|
// Initialise member variables
|
||||||
|
$this->_url = $pUrl;
|
||||||
|
$this->_tooltip = $pTooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get URL
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUrl() {
|
||||||
|
return $this->_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set URL
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_Hyperlink
|
||||||
|
*/
|
||||||
|
public function setUrl($value = '') {
|
||||||
|
$this->_url = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tooltip
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTooltip() {
|
||||||
|
return $this->_tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set tooltip
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Cell_Hyperlink
|
||||||
|
*/
|
||||||
|
public function setTooltip($value = '') {
|
||||||
|
$this->_tooltip = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this hyperlink internal? (to another sheet)
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isInternal() {
|
||||||
|
return strpos($this->_url, 'sheet://') !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode() {
|
||||||
|
return md5(
|
||||||
|
$this->_url
|
||||||
|
. $this->_tooltip
|
||||||
|
. __CLASS__
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Cell_IValueBinder
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Cell
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
interface PHPExcel_Cell_IValueBinder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bind value to a cell
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $cell Cell to bind value to
|
||||||
|
* @param mixed $value Value to bind in cell
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function bindValue(PHPExcel_Cell $cell, $value = null);
|
||||||
|
}
|
|
@ -0,0 +1,288 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Comment
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Comment implements PHPExcel_IComparable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Author
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_author;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rich text comment
|
||||||
|
*
|
||||||
|
* @var PHPExcel_RichText
|
||||||
|
*/
|
||||||
|
private $_text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment width (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_width = '96pt';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Left margin (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_marginLeft = '59.25pt';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Top margin (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_marginTop = '1.5pt';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visible
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_visible = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment height (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_height = '55.5pt';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment fill color
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Style_Color
|
||||||
|
*/
|
||||||
|
private $_fillColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Comment
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Initialise variables
|
||||||
|
$this->_author = 'Author';
|
||||||
|
$this->_text = new PHPExcel_RichText();
|
||||||
|
$this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Author
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAuthor() {
|
||||||
|
return $this->_author;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Author
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_Comment
|
||||||
|
*/
|
||||||
|
public function setAuthor($pValue = '') {
|
||||||
|
$this->_author = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Rich text comment
|
||||||
|
*
|
||||||
|
* @return PHPExcel_RichText
|
||||||
|
*/
|
||||||
|
public function getText() {
|
||||||
|
return $this->_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Rich text comment
|
||||||
|
*
|
||||||
|
* @param PHPExcel_RichText $pValue
|
||||||
|
* @return PHPExcel_Comment
|
||||||
|
*/
|
||||||
|
public function setText(PHPExcel_RichText $pValue) {
|
||||||
|
$this->_text = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get comment width (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getWidth() {
|
||||||
|
return $this->_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set comment width (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Comment
|
||||||
|
*/
|
||||||
|
public function setWidth($value = '96pt') {
|
||||||
|
$this->_width = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get comment height (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHeight() {
|
||||||
|
return $this->_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set comment height (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Comment
|
||||||
|
*/
|
||||||
|
public function setHeight($value = '55.5pt') {
|
||||||
|
$this->_height = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get left margin (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMarginLeft() {
|
||||||
|
return $this->_marginLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set left margin (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Comment
|
||||||
|
*/
|
||||||
|
public function setMarginLeft($value = '59.25pt') {
|
||||||
|
$this->_marginLeft = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get top margin (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMarginTop() {
|
||||||
|
return $this->_marginTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set top margin (CSS style, i.e. XXpx or YYpt)
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_Comment
|
||||||
|
*/
|
||||||
|
public function setMarginTop($value = '1.5pt') {
|
||||||
|
$this->_marginTop = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the comment visible by default?
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getVisible() {
|
||||||
|
return $this->_visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set comment default visibility
|
||||||
|
*
|
||||||
|
* @param boolean $value
|
||||||
|
* @return PHPExcel_Comment
|
||||||
|
*/
|
||||||
|
public function setVisible($value = false) {
|
||||||
|
$this->_visible = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get fill color
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style_Color
|
||||||
|
*/
|
||||||
|
public function getFillColor() {
|
||||||
|
return $this->_fillColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode() {
|
||||||
|
return md5(
|
||||||
|
$this->_author
|
||||||
|
. $this->_text->getHashCode()
|
||||||
|
. $this->_width
|
||||||
|
. $this->_height
|
||||||
|
. $this->_marginLeft
|
||||||
|
. $this->_marginTop
|
||||||
|
. ($this->_visible ? 1 : 0)
|
||||||
|
. $this->_fillColor->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,366 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_DocumentProperties
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_DocumentProperties
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creator
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_creator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LastModifiedBy
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_lastModifiedBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created
|
||||||
|
*
|
||||||
|
* @var datetime
|
||||||
|
*/
|
||||||
|
private $_created;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modified
|
||||||
|
*
|
||||||
|
* @var datetime
|
||||||
|
*/
|
||||||
|
private $_modified;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Title
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keywords
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_keywords;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Category
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Company
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_company;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Initialise values
|
||||||
|
$this->_creator = 'Unknown Creator';
|
||||||
|
$this->_lastModifiedBy = $this->_creator;
|
||||||
|
$this->_created = time();
|
||||||
|
$this->_modified = time();
|
||||||
|
$this->_title = "Untitled Spreadsheet";
|
||||||
|
$this->_subject = '';
|
||||||
|
$this->_description = '';
|
||||||
|
$this->_keywords = '';
|
||||||
|
$this->_category = '';
|
||||||
|
$this->_manager = '';
|
||||||
|
$this->_company = 'Microsoft Corporation';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Creator
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCreator() {
|
||||||
|
return $this->_creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Creator
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setCreator($pValue = '') {
|
||||||
|
$this->_creator = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Last Modified By
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLastModifiedBy() {
|
||||||
|
return $this->_lastModifiedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Last Modified By
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setLastModifiedBy($pValue = '') {
|
||||||
|
$this->_lastModifiedBy = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Created
|
||||||
|
*
|
||||||
|
* @return datetime
|
||||||
|
*/
|
||||||
|
public function getCreated() {
|
||||||
|
return $this->_created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Created
|
||||||
|
*
|
||||||
|
* @param datetime $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setCreated($pValue = null) {
|
||||||
|
if (is_null($pValue)) {
|
||||||
|
$pValue = time();
|
||||||
|
}
|
||||||
|
$this->_created = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Modified
|
||||||
|
*
|
||||||
|
* @return datetime
|
||||||
|
*/
|
||||||
|
public function getModified() {
|
||||||
|
return $this->_modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Modified
|
||||||
|
*
|
||||||
|
* @param datetime $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setModified($pValue = null) {
|
||||||
|
if (is_null($pValue)) {
|
||||||
|
$pValue = time();
|
||||||
|
}
|
||||||
|
$this->_modified = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Title
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTitle() {
|
||||||
|
return $this->_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Title
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setTitle($pValue = '') {
|
||||||
|
$this->_title = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Description
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription() {
|
||||||
|
return $this->_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Description
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setDescription($pValue = '') {
|
||||||
|
$this->_description = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Subject
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSubject() {
|
||||||
|
return $this->_subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Subject
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setSubject($pValue = '') {
|
||||||
|
$this->_subject = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Keywords
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getKeywords() {
|
||||||
|
return $this->_keywords;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Keywords
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setKeywords($pValue = '') {
|
||||||
|
$this->_keywords = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Category
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCategory() {
|
||||||
|
return $this->_category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Category
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setCategory($pValue = '') {
|
||||||
|
$this->_category = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Company
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCompany() {
|
||||||
|
return $this->_company;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Company
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setCompany($pValue = '') {
|
||||||
|
$this->_company = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Manager
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getManager() {
|
||||||
|
return $this->_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Manager
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @return PHPExcel_DocumentProperties
|
||||||
|
*/
|
||||||
|
public function setManager($pValue = '') {
|
||||||
|
$this->_manager = $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,218 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_DocumentSecurity
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_DocumentSecurity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* LockRevision
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_lockRevision;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LockStructure
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_lockStructure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LockWindows
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_lockWindows;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RevisionsPassword
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_revisionsPassword;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WorkbookPassword
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_workbookPassword;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Initialise values
|
||||||
|
$this->_lockRevision = false;
|
||||||
|
$this->_lockStructure = false;
|
||||||
|
$this->_lockWindows = false;
|
||||||
|
$this->_revisionsPassword = '';
|
||||||
|
$this->_workbookPassword = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is some sort of dcument security enabled?
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function isSecurityEnabled() {
|
||||||
|
return $this->_lockRevision ||
|
||||||
|
$this->_lockStructure ||
|
||||||
|
$this->_lockWindows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LockRevision
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function getLockRevision() {
|
||||||
|
return $this->_lockRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set LockRevision
|
||||||
|
*
|
||||||
|
* @param boolean $pValue
|
||||||
|
* @return PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
function setLockRevision($pValue = false) {
|
||||||
|
$this->_lockRevision = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LockStructure
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function getLockStructure() {
|
||||||
|
return $this->_lockStructure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set LockStructure
|
||||||
|
*
|
||||||
|
* @param boolean $pValue
|
||||||
|
* @return PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
function setLockStructure($pValue = false) {
|
||||||
|
$this->_lockStructure = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LockWindows
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function getLockWindows() {
|
||||||
|
return $this->_lockWindows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set LockWindows
|
||||||
|
*
|
||||||
|
* @param boolean $pValue
|
||||||
|
* @return PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
function setLockWindows($pValue = false) {
|
||||||
|
$this->_lockWindows = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get RevisionsPassword (hashed)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getRevisionsPassword() {
|
||||||
|
return $this->_revisionsPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set RevisionsPassword
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @param boolean $pAlreadyHashed If the password has already been hashed, set this to true
|
||||||
|
* @return PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
function setRevisionsPassword($pValue = '', $pAlreadyHashed = false) {
|
||||||
|
if (!$pAlreadyHashed) {
|
||||||
|
$pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue);
|
||||||
|
}
|
||||||
|
$this->_revisionsPassword = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get WorkbookPassword (hashed)
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getWorkbookPassword() {
|
||||||
|
return $this->_workbookPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set WorkbookPassword
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
* @param boolean $pAlreadyHashed If the password has already been hashed, set this to true
|
||||||
|
* @return PHPExcel_DocumentSecurity
|
||||||
|
*/
|
||||||
|
function setWorkbookPassword($pValue = '', $pAlreadyHashed = false) {
|
||||||
|
if (!$pAlreadyHashed) {
|
||||||
|
$pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue);
|
||||||
|
}
|
||||||
|
$this->_workbookPassword = $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,200 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_HashTable
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_HashTable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* HashTable elements
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $_items = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HashTable key map
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $_keyMap = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_HashTable
|
||||||
|
*
|
||||||
|
* @param PHPExcel_IComparable[] $pSource Optional source array to create HashTable from
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct($pSource = null)
|
||||||
|
{
|
||||||
|
if (!is_null($pSource)) {
|
||||||
|
// Create HashTable
|
||||||
|
$this->addFromSource($pSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add HashTable items from source
|
||||||
|
*
|
||||||
|
* @param PHPExcel_IComparable[] $pSource Source array to create HashTable from
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function addFromSource($pSource = null) {
|
||||||
|
// Check if an array was passed
|
||||||
|
if ($pSource == null) {
|
||||||
|
return;
|
||||||
|
} else if (!is_array($pSource)) {
|
||||||
|
throw new Exception('Invalid array parameter passed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($pSource as $item) {
|
||||||
|
$this->add($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add HashTable item
|
||||||
|
*
|
||||||
|
* @param PHPExcel_IComparable $pSource Item to add
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function add(PHPExcel_IComparable $pSource = null) {
|
||||||
|
if (!isset($this->_items[ $pSource->getHashCode() ])) {
|
||||||
|
$this->_items[ $pSource->getHashCode() ] = $pSource;
|
||||||
|
$this->_keyMap[ count($this->_items) - 1 ] = $pSource->getHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove HashTable item
|
||||||
|
*
|
||||||
|
* @param PHPExcel_IComparable $pSource Item to remove
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function remove(PHPExcel_IComparable $pSource = null) {
|
||||||
|
if (isset($this->_items[ $pSource->getHashCode() ])) {
|
||||||
|
unset($this->_items[ $pSource->getHashCode() ]);
|
||||||
|
|
||||||
|
$deleteKey = -1;
|
||||||
|
foreach ($this->_keyMap as $key => $value) {
|
||||||
|
if ($deleteKey >= 0) {
|
||||||
|
$this->_keyMap[$key - 1] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value == $pSource->getHashCode()) {
|
||||||
|
$deleteKey = $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($this->_keyMap[ count($this->_keyMap) - 1 ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear HashTable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function clear() {
|
||||||
|
$this->_items = array();
|
||||||
|
$this->_keyMap = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function count() {
|
||||||
|
return count($this->_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get index for hash code
|
||||||
|
*
|
||||||
|
* @param string $pHashCode
|
||||||
|
* @return int Index
|
||||||
|
*/
|
||||||
|
public function getIndexForHashCode($pHashCode = '') {
|
||||||
|
return array_search($pHashCode, $this->_keyMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get by index
|
||||||
|
*
|
||||||
|
* @param int $pIndex
|
||||||
|
* @return PHPExcel_IComparable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function getByIndex($pIndex = 0) {
|
||||||
|
if (isset($this->_keyMap[$pIndex])) {
|
||||||
|
return $this->getByHashCode( $this->_keyMap[$pIndex] );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get by hashcode
|
||||||
|
*
|
||||||
|
* @param string $pHashCode
|
||||||
|
* @return PHPExcel_IComparable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function getByHashCode($pHashCode = '') {
|
||||||
|
if (isset($this->_items[$pHashCode])) {
|
||||||
|
return $this->_items[$pHashCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HashTable to array
|
||||||
|
*
|
||||||
|
* @return PHPExcel_IComparable[]
|
||||||
|
*/
|
||||||
|
public function toArray() {
|
||||||
|
return $this->_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_IComparable
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
interface PHPExcel_IComparable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,277 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 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 */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_IOFactory
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_IOFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Search locations
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access private
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
private static $_searchLocations = array(
|
||||||
|
array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ),
|
||||||
|
array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' )
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autoresolve classes
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access private
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
private static $_autoResolveClasses = array(
|
||||||
|
'Excel2007',
|
||||||
|
'Excel5',
|
||||||
|
'Excel2003XML',
|
||||||
|
'OOCalc',
|
||||||
|
'SYLK',
|
||||||
|
'Serialized',
|
||||||
|
'CSV',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor for PHPExcel_IOFactory
|
||||||
|
*/
|
||||||
|
private function __construct() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get search locations
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getSearchLocations() {
|
||||||
|
return self::$_searchLocations;
|
||||||
|
} // function getSearchLocations()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set search locations
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param array $value
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function setSearchLocations($value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
self::$_searchLocations = $value;
|
||||||
|
} else {
|
||||||
|
throw new Exception('Invalid parameter passed.');
|
||||||
|
}
|
||||||
|
} // function setSearchLocations()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add search location
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $type Example: IWriter
|
||||||
|
* @param string $location Example: PHPExcel/Writer/{0}.php
|
||||||
|
* @param string $classname Example: PHPExcel_Writer_{0}
|
||||||
|
*/
|
||||||
|
public static function addSearchLocation($type = '', $location = '', $classname = '') {
|
||||||
|
self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname );
|
||||||
|
} // function addSearchLocation()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create PHPExcel_Writer_IWriter
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param PHPExcel $phpExcel
|
||||||
|
* @param string $writerType Example: Excel2007
|
||||||
|
* @return PHPExcel_Writer_IWriter
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function createWriter(PHPExcel $phpExcel, $writerType = '') {
|
||||||
|
// Search type
|
||||||
|
$searchType = 'IWriter';
|
||||||
|
|
||||||
|
// Include class
|
||||||
|
foreach (self::$_searchLocations as $searchLocation) {
|
||||||
|
if ($searchLocation['type'] == $searchType) {
|
||||||
|
$className = str_replace('{0}', $writerType, $searchLocation['class']);
|
||||||
|
$classFile = str_replace('{0}', $writerType, $searchLocation['path']);
|
||||||
|
|
||||||
|
$instance = new $className($phpExcel);
|
||||||
|
if (!is_null($instance)) {
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing found...
|
||||||
|
throw new Exception("No $searchType found for type $writerType");
|
||||||
|
} // function createWriter()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create PHPExcel_Reader_IReader
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $readerType Example: Excel2007
|
||||||
|
* @return PHPExcel_Reader_IReader
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function createReader($readerType = '') {
|
||||||
|
// Search type
|
||||||
|
$searchType = 'IReader';
|
||||||
|
|
||||||
|
// Include class
|
||||||
|
foreach (self::$_searchLocations as $searchLocation) {
|
||||||
|
if ($searchLocation['type'] == $searchType) {
|
||||||
|
$className = str_replace('{0}', $readerType, $searchLocation['class']);
|
||||||
|
$classFile = str_replace('{0}', $readerType, $searchLocation['path']);
|
||||||
|
|
||||||
|
$instance = new $className();
|
||||||
|
if (!is_null($instance)) {
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing found...
|
||||||
|
throw new Exception("No $searchType found for type $readerType");
|
||||||
|
} // function createReader()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function load($pFilename) {
|
||||||
|
$reader = self::createReaderForFile($pFilename);
|
||||||
|
return $reader->load($pFilename);
|
||||||
|
} // function load()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify file type using automatic PHPExcel_Reader_IReader resolution
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function identify($pFilename) {
|
||||||
|
$reader = self::createReaderForFile($pFilename);
|
||||||
|
$className = get_class($reader);
|
||||||
|
$classType = explode('_',$className);
|
||||||
|
unset($reader);
|
||||||
|
return array_pop($classType);
|
||||||
|
} // function identify()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return PHPExcel_Reader_IReader
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function createReaderForFile($pFilename) {
|
||||||
|
|
||||||
|
// First, lucky guess by inspecting file extension
|
||||||
|
$pathinfo = pathinfo($pFilename);
|
||||||
|
|
||||||
|
if (isset($pathinfo['extension'])) {
|
||||||
|
switch (strtolower($pathinfo['extension'])) {
|
||||||
|
case 'xlsx':
|
||||||
|
$reader = self::createReader('Excel2007');
|
||||||
|
break;
|
||||||
|
case 'xls':
|
||||||
|
$reader = self::createReader('Excel5');
|
||||||
|
break;
|
||||||
|
case 'ods':
|
||||||
|
$reader = self::createReader('OOCalc');
|
||||||
|
break;
|
||||||
|
case 'slk':
|
||||||
|
$reader = self::createReader('SYLK');
|
||||||
|
break;
|
||||||
|
case 'xml':
|
||||||
|
$reader = self::createReader('Excel2003XML');
|
||||||
|
break;
|
||||||
|
case 'csv':
|
||||||
|
// Do nothing
|
||||||
|
// We must not try to use CSV reader since it loads
|
||||||
|
// all files including Excel files etc.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's see if we are lucky
|
||||||
|
if (isset($reader) && $reader->canRead($pFilename)) {
|
||||||
|
return $reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach here then "lucky guess" didn't give any result
|
||||||
|
|
||||||
|
// Try loading using self::$_autoResolveClasses
|
||||||
|
foreach (self::$_autoResolveClasses as $autoResolveClass) {
|
||||||
|
$reader = self::createReader($autoResolveClass);
|
||||||
|
if ($reader->canRead($pFilename)) {
|
||||||
|
return $reader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // function createReaderForFile()
|
||||||
|
}
|
|
@ -0,0 +1,245 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_NamedRange
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_NamedRange
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Range name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Worksheet on which the named range can be resolved
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
private $_worksheet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range of the referenced cells
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_range;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the named range local? (i.e. can only be used on $this->_worksheet)
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $_localOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
private $_scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new NamedRange
|
||||||
|
*
|
||||||
|
* @param string $pName
|
||||||
|
* @param PHPExcel_Worksheet $pWorksheet
|
||||||
|
* @param string $pRange
|
||||||
|
* @param bool $pLocalOnly
|
||||||
|
* @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope.
|
||||||
|
*/
|
||||||
|
public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null)
|
||||||
|
{
|
||||||
|
// Validate data
|
||||||
|
if (is_null($pName) || is_null($pWorksheet)|| is_null($pRange)) {
|
||||||
|
throw new Exception('Parameters can not be null.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set local members
|
||||||
|
$this->_name = $pName;
|
||||||
|
$this->_worksheet = $pWorksheet;
|
||||||
|
$this->_range = $pRange;
|
||||||
|
$this->_localOnly = $pLocalOnly;
|
||||||
|
$this->_scope = ($pLocalOnly == true) ?
|
||||||
|
(($pScope == null) ? $pWorksheet : $pScope) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName() {
|
||||||
|
return $this->_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set name
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_NamedRange
|
||||||
|
*/
|
||||||
|
public function setName($value = null) {
|
||||||
|
if (!is_null($value)) {
|
||||||
|
// Old title
|
||||||
|
$oldTitle = $this->_name;
|
||||||
|
|
||||||
|
// Re-attach
|
||||||
|
if (!is_null($this->_worksheet)) {
|
||||||
|
$this->_worksheet->getParent()->removeNamedRange($this->_name,$this->_worksheet);
|
||||||
|
}
|
||||||
|
$this->_name = $value;
|
||||||
|
|
||||||
|
if (!is_null($this->_worksheet)) {
|
||||||
|
$this->_worksheet->getParent()->addNamedRange($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New title
|
||||||
|
$newTitle = $this->_name;
|
||||||
|
PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_worksheet->getParent(), $oldTitle, $newTitle);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get worksheet
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Worksheet
|
||||||
|
*/
|
||||||
|
public function getWorksheet() {
|
||||||
|
return $this->_worksheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set worksheet
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Worksheet $value
|
||||||
|
* @return PHPExcel_NamedRange
|
||||||
|
*/
|
||||||
|
public function setWorksheet(PHPExcel_Worksheet $value = null) {
|
||||||
|
if (!is_null($value)) {
|
||||||
|
$this->_worksheet = $value;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get range
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRange() {
|
||||||
|
return $this->_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set range
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return PHPExcel_NamedRange
|
||||||
|
*/
|
||||||
|
public function setRange($value = null) {
|
||||||
|
if (!is_null($value)) {
|
||||||
|
$this->_range = $value;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get localOnly
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getLocalOnly() {
|
||||||
|
return $this->_localOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set localOnly
|
||||||
|
*
|
||||||
|
* @param bool $value
|
||||||
|
* @return PHPExcel_NamedRange
|
||||||
|
*/
|
||||||
|
public function setLocalOnly($value = false) {
|
||||||
|
$this->_localOnly = $value;
|
||||||
|
$this->_scope = $value ? $this->_worksheet : null;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get scope
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Worksheet|null
|
||||||
|
*/
|
||||||
|
public function getScope() {
|
||||||
|
return $this->_scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set scope
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Worksheet|null $value
|
||||||
|
* @return PHPExcel_NamedRange
|
||||||
|
*/
|
||||||
|
public function setScope(PHPExcel_Worksheet $value = null) {
|
||||||
|
$this->_scope = $value;
|
||||||
|
$this->_localOnly = ($value == null) ? false : true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a named range to a regular cell range
|
||||||
|
*
|
||||||
|
* @param string $pNamedRange Named range
|
||||||
|
* @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope
|
||||||
|
* @return PHPExcel_NamedRange
|
||||||
|
*/
|
||||||
|
public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) {
|
||||||
|
return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,351 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** PHPExcel root directory */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_CSV
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Input encoding
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_inputEncoding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delimiter
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_delimiter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enclosure
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_enclosure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Line ending
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_lineEnding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sheet index to read
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_sheetIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_IReadFilter instance
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
private $_readFilter = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Reader_CSV
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->_inputEncoding = 'UTF-8';
|
||||||
|
$this->_delimiter = ',';
|
||||||
|
$this->_enclosure = '"';
|
||||||
|
$this->_lineEnding = PHP_EOL;
|
||||||
|
$this->_sheetIndex = 0;
|
||||||
|
$this->_readFilter = new PHPExcel_Reader_DefaultReadFilter();
|
||||||
|
} // function __construct()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the current PHPExcel_Reader_IReader read the file?
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return boolean
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function canRead($pFilename)
|
||||||
|
{
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} // function canRead()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $pFilename
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function load($pFilename)
|
||||||
|
{
|
||||||
|
// Create new PHPExcel
|
||||||
|
$objPHPExcel = new PHPExcel();
|
||||||
|
|
||||||
|
// Load into this instance
|
||||||
|
return $this->loadIntoExisting($pFilename, $objPHPExcel);
|
||||||
|
} // function load()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read filter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
public function getReadFilter() {
|
||||||
|
return $this->_readFilter;
|
||||||
|
} // function getReadFilter()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read filter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param PHPExcel_Reader_IReadFilter $pValue
|
||||||
|
*/
|
||||||
|
public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) {
|
||||||
|
$this->_readFilter = $pValue;
|
||||||
|
return $this;
|
||||||
|
} // function setReadFilter()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set input encoding
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $pValue Input encoding
|
||||||
|
*/
|
||||||
|
public function setInputEncoding($pValue = 'UTF-8')
|
||||||
|
{
|
||||||
|
$this->_inputEncoding = $pValue;
|
||||||
|
return $this;
|
||||||
|
} // function setInputEncoding()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get input encoding
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getInputEncoding()
|
||||||
|
{
|
||||||
|
return $this->_inputEncoding;
|
||||||
|
} // function getInputEncoding()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file into PHPExcel instance
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $pFilename
|
||||||
|
* @param PHPExcel $objPHPExcel
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
|
||||||
|
{
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new PHPExcel
|
||||||
|
while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) {
|
||||||
|
$objPHPExcel->createSheet();
|
||||||
|
}
|
||||||
|
$objPHPExcel->setActiveSheetIndex( $this->_sheetIndex );
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
$fileHandle = fopen($pFilename, 'r');
|
||||||
|
if ($fileHandle === false) {
|
||||||
|
throw new Exception("Could not open file $pFilename for reading.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip BOM, if any
|
||||||
|
switch ($this->_inputEncoding) {
|
||||||
|
case 'UTF-8':
|
||||||
|
fgets($fileHandle, 4) == "\xEF\xBB\xBF" ?
|
||||||
|
fseek($fileHandle, 3) : fseek($fileHandle, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through file
|
||||||
|
$currentRow = 0;
|
||||||
|
$rowData = array();
|
||||||
|
while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) {
|
||||||
|
++$currentRow;
|
||||||
|
$rowDataCount = count($rowData);
|
||||||
|
for ($i = 0; $i < $rowDataCount; ++$i) {
|
||||||
|
$columnLetter = PHPExcel_Cell::stringFromColumnIndex($i);
|
||||||
|
if ($rowData[$i] != '' && $this->_readFilter->readCell($columnLetter, $currentRow)) {
|
||||||
|
// Unescape enclosures
|
||||||
|
$rowData[$i] = str_replace("\\" . $this->_enclosure, $this->_enclosure, $rowData[$i]);
|
||||||
|
$rowData[$i] = str_replace($this->_enclosure . $this->_enclosure, $this->_enclosure, $rowData[$i]);
|
||||||
|
|
||||||
|
// Convert encoding if necessary
|
||||||
|
if ($this->_inputEncoding !== 'UTF-8') {
|
||||||
|
$rowData[$i] = PHPExcel_Shared_String::ConvertEncoding($rowData[$i], 'UTF-8', $this->_inputEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cell value
|
||||||
|
$objPHPExcel->getActiveSheet()->getCell($columnLetter . $currentRow)->setValue($rowData[$i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close file
|
||||||
|
fclose($fileHandle);
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return $objPHPExcel;
|
||||||
|
} // function loadIntoExisting()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get delimiter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDelimiter() {
|
||||||
|
return $this->_delimiter;
|
||||||
|
} // function getDelimiter()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set delimiter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $pValue Delimiter, defaults to ,
|
||||||
|
* @return PHPExcel_Reader_CSV
|
||||||
|
*/
|
||||||
|
public function setDelimiter($pValue = ',') {
|
||||||
|
$this->_delimiter = $pValue;
|
||||||
|
return $this;
|
||||||
|
} // function setDelimiter()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get enclosure
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEnclosure() {
|
||||||
|
return $this->_enclosure;
|
||||||
|
} // function getEnclosure()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set enclosure
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $pValue Enclosure, defaults to "
|
||||||
|
* @return PHPExcel_Reader_CSV
|
||||||
|
*/
|
||||||
|
public function setEnclosure($pValue = '"') {
|
||||||
|
if ($pValue == '') {
|
||||||
|
$pValue = '"';
|
||||||
|
}
|
||||||
|
$this->_enclosure = $pValue;
|
||||||
|
return $this;
|
||||||
|
} // function setEnclosure()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get line ending
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLineEnding() {
|
||||||
|
return $this->_lineEnding;
|
||||||
|
} // function getLineEnding()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set line ending
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $pValue Line ending, defaults to OS line ending (PHP_EOL)
|
||||||
|
* @return PHPExcel_Reader_CSV
|
||||||
|
*/
|
||||||
|
public function setLineEnding($pValue = PHP_EOL) {
|
||||||
|
$this->_lineEnding = $pValue;
|
||||||
|
return $this;
|
||||||
|
} // function setLineEnding()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet index
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getSheetIndex() {
|
||||||
|
return $this->_sheetIndex;
|
||||||
|
} // function getSheetIndex()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sheet index
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param int $pValue Sheet index
|
||||||
|
* @return PHPExcel_Reader_CSV
|
||||||
|
*/
|
||||||
|
public function setSheetIndex($pValue = 0) {
|
||||||
|
$this->_sheetIndex = $pValue;
|
||||||
|
return $this;
|
||||||
|
} // function setSheetIndex()
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** PHPExcel root directory */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_DefaultReadFilter
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Should this cell be read?
|
||||||
|
*
|
||||||
|
* @param $column String column index
|
||||||
|
* @param $row Row index
|
||||||
|
* @param $worksheetName Optional worksheet name
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function readCell($column, $row, $worksheetName = '') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,693 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** PHPExcel root directory */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_Excel2003XML
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read data only?
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_readDataOnly = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restict which sheets should be loaded?
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $_loadSheetsOnly = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sheet index to read
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_sheetIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $_styles = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_IReadFilter instance
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
private $_readFilter = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data only?
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getReadDataOnly() {
|
||||||
|
return $this->_readDataOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read data only
|
||||||
|
*
|
||||||
|
* @param boolean $pValue
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setReadDataOnly($pValue = false) {
|
||||||
|
$this->_readDataOnly = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get which sheets to load
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getLoadSheetsOnly()
|
||||||
|
{
|
||||||
|
return $this->_loadSheetsOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set which sheets to load
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setLoadSheetsOnly($value = null)
|
||||||
|
{
|
||||||
|
$this->_loadSheetsOnly = is_array($value) ?
|
||||||
|
$value : array($value);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all sheets to load
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setLoadAllSheets()
|
||||||
|
{
|
||||||
|
$this->_loadSheetsOnly = null;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read filter
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
public function getReadFilter() {
|
||||||
|
return $this->_readFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read filter
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Reader_IReadFilter $pValue
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) {
|
||||||
|
$this->_readFilter = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Reader_Excel2003XML
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->_sheetIndex = 0;
|
||||||
|
$this->_readFilter = new PHPExcel_Reader_DefaultReadFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the current PHPExcel_Reader_IReader read the file?
|
||||||
|
*
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canRead($pFilename)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Office xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||||
|
// Excel xmlns:x="urn:schemas-microsoft-com:office:excel"
|
||||||
|
// XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
|
||||||
|
// Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet"
|
||||||
|
// XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
|
||||||
|
// XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
|
||||||
|
// MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset"
|
||||||
|
// Rowset xmlns:z="#RowsetSchema"
|
||||||
|
//
|
||||||
|
|
||||||
|
$signature = array(
|
||||||
|
'<?xml version="1.0"?>',
|
||||||
|
'<?mso-application progid="Excel.Sheet"?>'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read sample data (first 2 KB will do)
|
||||||
|
$fh = fopen($pFilename, 'r');
|
||||||
|
$data = fread($fh, 2048);
|
||||||
|
fclose($fh);
|
||||||
|
|
||||||
|
$headers = explode("\n",$data);
|
||||||
|
$valid = true;
|
||||||
|
foreach($signature as $key => $match) {
|
||||||
|
if (isset($headers[$key])) {
|
||||||
|
$line = trim(rtrim($headers[$key], "\r\n"));
|
||||||
|
if ($line != $match) {
|
||||||
|
$valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function load($pFilename)
|
||||||
|
{
|
||||||
|
// Create new PHPExcel
|
||||||
|
$objPHPExcel = new PHPExcel();
|
||||||
|
|
||||||
|
// Load into this instance
|
||||||
|
return $this->loadIntoExisting($pFilename, $objPHPExcel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) {
|
||||||
|
$styleAttributeValue = strtolower($styleAttributeValue);
|
||||||
|
foreach($styleList as $style) {
|
||||||
|
if ($styleAttributeValue == strtolower($style)) {
|
||||||
|
$styleAttributeValue = $style;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pixel units to excel width units(units of 1/256th of a character width)
|
||||||
|
* @param pxs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static function _pixel2WidthUnits($pxs) {
|
||||||
|
$UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219);
|
||||||
|
|
||||||
|
$widthUnits = 256 * ($pxs / 7);
|
||||||
|
$widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)];
|
||||||
|
return $widthUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* excel width units(units of 1/256th of a character width) to pixel units
|
||||||
|
* @param widthUnits
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static function _widthUnits2Pixel($widthUnits) {
|
||||||
|
$pixels = ($widthUnits / 256) * 7;
|
||||||
|
$offsetWidthUnits = $widthUnits % 256;
|
||||||
|
$pixels += round($offsetWidthUnits / (256 / 7));
|
||||||
|
return $pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file into PHPExcel instance
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @param PHPExcel $objPHPExcel
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
|
||||||
|
{
|
||||||
|
$fromFormats = array('\-', '\ ');
|
||||||
|
$toFormats = array('-', ' ');
|
||||||
|
|
||||||
|
$underlineStyles = array (
|
||||||
|
PHPExcel_Style_Font::UNDERLINE_NONE,
|
||||||
|
PHPExcel_Style_Font::UNDERLINE_DOUBLE,
|
||||||
|
PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING,
|
||||||
|
PHPExcel_Style_Font::UNDERLINE_SINGLE,
|
||||||
|
PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING
|
||||||
|
);
|
||||||
|
$verticalAlignmentStyles = array (
|
||||||
|
PHPExcel_Style_Alignment::VERTICAL_BOTTOM,
|
||||||
|
PHPExcel_Style_Alignment::VERTICAL_TOP,
|
||||||
|
PHPExcel_Style_Alignment::VERTICAL_CENTER,
|
||||||
|
PHPExcel_Style_Alignment::VERTICAL_JUSTIFY
|
||||||
|
);
|
||||||
|
$horizontalAlignmentStyles = array (
|
||||||
|
PHPExcel_Style_Alignment::HORIZONTAL_GENERAL,
|
||||||
|
PHPExcel_Style_Alignment::HORIZONTAL_LEFT,
|
||||||
|
PHPExcel_Style_Alignment::HORIZONTAL_RIGHT,
|
||||||
|
PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
|
||||||
|
PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS,
|
||||||
|
PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$xml = simplexml_load_file($pFilename);
|
||||||
|
$namespaces = $xml->getNamespaces(true);
|
||||||
|
// echo '<pre>';
|
||||||
|
// print_r($namespaces);
|
||||||
|
// echo '</pre><hr />';
|
||||||
|
//
|
||||||
|
// echo '<pre>';
|
||||||
|
// print_r($xml);
|
||||||
|
// echo '</pre><hr />';
|
||||||
|
//
|
||||||
|
$docProps = $objPHPExcel->getProperties();
|
||||||
|
foreach($xml->DocumentProperties[0] as $propertyName => $propertyValue) {
|
||||||
|
switch ($propertyName) {
|
||||||
|
case 'Title' :
|
||||||
|
$docProps->setTitle($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'Subject' :
|
||||||
|
$docProps->setSubject($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'Author' :
|
||||||
|
$docProps->setCreator($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'Created' :
|
||||||
|
$creationDate = strtotime($propertyValue);
|
||||||
|
$docProps->setCreated($creationDate);
|
||||||
|
break;
|
||||||
|
case 'LastAuthor' :
|
||||||
|
$docProps->setLastModifiedBy($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'Company' :
|
||||||
|
$docProps->setCompany($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'Category' :
|
||||||
|
$docProps->setCategory($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'Keywords' :
|
||||||
|
$docProps->setKeywords($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'Description' :
|
||||||
|
$docProps->setDescription($propertyValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach($xml->Styles[0] as $style) {
|
||||||
|
$style_ss = $style->attributes($namespaces['ss']);
|
||||||
|
$styleID = (string) $style_ss['ID'];
|
||||||
|
// echo 'Style ID = '.$styleID.'<br />';
|
||||||
|
if ($styleID == 'Default') {
|
||||||
|
$this->_styles['Default'] = array();
|
||||||
|
} else {
|
||||||
|
$this->_styles[$styleID] = $this->_styles['Default'];
|
||||||
|
}
|
||||||
|
foreach ($style as $styleType => $styleData) {
|
||||||
|
$styleAttributes = $styleData->attributes($namespaces['ss']);
|
||||||
|
// echo $styleType.'<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 (count($thisBorder) > 0) {
|
||||||
|
if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) {
|
||||||
|
$this->_styles[$styleID]['borders'][$borderPosition] = $thisBorder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Font' :
|
||||||
|
foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
|
||||||
|
// echo $styleAttributeKey.' = '.$styleAttributeValue.'<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;
|
||||||
|
foreach($xml->Worksheet as $worksheet) {
|
||||||
|
$worksheet_ss = $worksheet->attributes($namespaces['ss']);
|
||||||
|
if ((isset($this->_loadSheetsOnly)) && (isset($worksheet_ss['Name'])) &&
|
||||||
|
(!in_array($worksheet_ss['Name'], $this->_loadSheetsOnly))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new Worksheet
|
||||||
|
$objPHPExcel->createSheet();
|
||||||
|
$objPHPExcel->setActiveSheetIndex($worksheetID);
|
||||||
|
if (isset($worksheet_ss['Name'])) {
|
||||||
|
$worksheetName = (string) $worksheet_ss['Name'];
|
||||||
|
$objPHPExcel->getActiveSheet()->setTitle($worksheetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnID = 'A';
|
||||||
|
foreach($worksheet->Table->Column as $columnData) {
|
||||||
|
$columnData_ss = $columnData->attributes($namespaces['ss']);
|
||||||
|
if (isset($columnData_ss['Index'])) {
|
||||||
|
$columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1);
|
||||||
|
}
|
||||||
|
if (isset($columnData_ss['Width'])) {
|
||||||
|
$columnWidth = $columnData_ss['Width'];
|
||||||
|
// echo '<b>Setting column width for '.$columnID.' to '.$columnWidth.'</b><br />';
|
||||||
|
$objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4);
|
||||||
|
}
|
||||||
|
++$columnID;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rowID = 1;
|
||||||
|
foreach($worksheet->Table->Row as $rowData) {
|
||||||
|
$row_ss = $rowData->attributes($namespaces['ss']);
|
||||||
|
if (isset($row_ss['Index'])) {
|
||||||
|
$rowID = (integer) $row_ss['Index'];
|
||||||
|
}
|
||||||
|
// echo '<b>Row '.$rowID.'</b><br />';
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
$columnID = 'A';
|
||||||
|
foreach($rowData->Cell as $cell) {
|
||||||
|
|
||||||
|
$cell_ss = $cell->attributes($namespaces['ss']);
|
||||||
|
if (isset($cell_ss['Index'])) {
|
||||||
|
$columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1);
|
||||||
|
}
|
||||||
|
$cellRange = $columnID.$rowID;
|
||||||
|
|
||||||
|
if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) {
|
||||||
|
$columnTo = $columnID;
|
||||||
|
if (isset($cell_ss['MergeAcross'])) {
|
||||||
|
$columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1);
|
||||||
|
}
|
||||||
|
$rowTo = $rowID;
|
||||||
|
if (isset($cell_ss['MergeDown'])) {
|
||||||
|
$rowTo = $rowTo + $cell_ss['MergeDown'];
|
||||||
|
}
|
||||||
|
$cellRange .= ':'.$columnTo.$rowTo;
|
||||||
|
$objPHPExcel->getActiveSheet()->mergeCells($cellRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasCalculatedValue = false;
|
||||||
|
$cellDataFormula = '';
|
||||||
|
if (isset($cell_ss['Formula'])) {
|
||||||
|
$cellDataFormula = $cell_ss['Formula'];
|
||||||
|
// 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 = 's';
|
||||||
|
const TYPE_INLINE = 'inlineStr';
|
||||||
|
const TYPE_ERROR = 'e';
|
||||||
|
*/
|
||||||
|
case 'String' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_STRING;
|
||||||
|
break;
|
||||||
|
case 'Number' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
|
||||||
|
$cellValue = (float) $cellValue;
|
||||||
|
if (floor($cellValue) == $cellValue) {
|
||||||
|
$cellValue = (integer) $cellValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Boolean' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_BOOL;
|
||||||
|
$cellValue = ($cellValue != 0);
|
||||||
|
break;
|
||||||
|
case 'DateTime' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
|
||||||
|
$cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue));
|
||||||
|
break;
|
||||||
|
case 'Error' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($hasCalculatedValue) {
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_FORMULA;
|
||||||
|
$columnNumber = PHPExcel_Cell::columnIndexFromString($columnID);
|
||||||
|
// Convert R1C1 style references to A1 style references (but only when not quoted)
|
||||||
|
$temp = explode('"',$cellDataFormula);
|
||||||
|
foreach($temp as $key => &$value) {
|
||||||
|
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
||||||
|
if (($key % 2) == 0) {
|
||||||
|
preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE);
|
||||||
|
// Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way
|
||||||
|
// through the formula from left to right. Reversing means that we work right to left.through
|
||||||
|
// the formula
|
||||||
|
$cellReferences = array_reverse($cellReferences);
|
||||||
|
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
|
||||||
|
// then modify the formula to use that new reference
|
||||||
|
foreach($cellReferences as $cellReference) {
|
||||||
|
$rowReference = $cellReference[2][0];
|
||||||
|
// Empty R reference is the current row
|
||||||
|
if ($rowReference == '') $rowReference = $rowID;
|
||||||
|
// Bracketed R references are relative to the current row
|
||||||
|
if ($rowReference{0} == '[') $rowReference = $rowID + trim($rowReference,'[]');
|
||||||
|
$columnReference = $cellReference[4][0];
|
||||||
|
// Empty C reference is the current column
|
||||||
|
if ($columnReference == '') $columnReference = $columnNumber;
|
||||||
|
// Bracketed C references are relative to the current column
|
||||||
|
if ($columnReference{0} == '[') $columnReference = $columnNumber + trim($columnReference,'[]');
|
||||||
|
$A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference;
|
||||||
|
$value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($value);
|
||||||
|
// Then rebuild the formula string
|
||||||
|
$cellDataFormula = implode('"',$temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'<br />';
|
||||||
|
//
|
||||||
|
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue),$type);
|
||||||
|
if ($hasCalculatedValue) {
|
||||||
|
// echo 'Forumla result is '.$cellValue.'<br />';
|
||||||
|
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($cell_ss['StyleID'])) {
|
||||||
|
$style = (string) $cell_ss['StyleID'];
|
||||||
|
// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'<br />';
|
||||||
|
if ((isset($this->_styles[$style])) && (count($this->_styles[$style]) > 0)) {
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
++$rowID;
|
||||||
|
}
|
||||||
|
++$worksheetID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return $objPHPExcel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet index
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getSheetIndex() {
|
||||||
|
return $this->_sheetIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sheet index
|
||||||
|
*
|
||||||
|
* @param int $pValue Sheet index
|
||||||
|
* @return PHPExcel_Reader_Excel2003XML
|
||||||
|
*/
|
||||||
|
public function setSheetIndex($pValue = 0) {
|
||||||
|
$this->_sheetIndex = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,677 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader_Excel5
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_Excel5_Escher
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader_Excel5
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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 = $this->_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 = $this->_GetInt2d($this->_data, $this->_pos);
|
||||||
|
|
||||||
|
// offset: 2; size: 2: Record Type
|
||||||
|
$fbt = $this->_GetInt2d($this->_data, $this->_pos + 2);
|
||||||
|
|
||||||
|
// bit: 0-3; mask: 0x000F; recVer
|
||||||
|
$recVer = (0x000F & $verInstance) >> 0;
|
||||||
|
|
||||||
|
$length = $this->_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 = $this->_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 = $this->_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 = $this->_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 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4;
|
||||||
|
|
||||||
|
$length = $this->_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 = $this->_GetInt2d($recordData, 18);
|
||||||
|
|
||||||
|
// offset: 20; size: 4; size of BLIP in bytes
|
||||||
|
$size = $this->_GetInt4d($recordData, 20);
|
||||||
|
|
||||||
|
// offset: 24; size: 4; number of references to this BLIP
|
||||||
|
$cRef = $this->_GetInt4d($recordData, 24);
|
||||||
|
|
||||||
|
// offset: 28; size: 4; MSOFO file offset
|
||||||
|
$foDelay = $this->_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 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4;
|
||||||
|
|
||||||
|
$length = $this->_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 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4;
|
||||||
|
|
||||||
|
$length = $this->_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 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4;
|
||||||
|
|
||||||
|
$length = $this->_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 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4;
|
||||||
|
|
||||||
|
$length = $this->_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 = $this->_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 = $this->_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 = $this->_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 = $this->_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 = $this->_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 = $this->_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 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4;
|
||||||
|
|
||||||
|
$length = $this->_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 & $this->_GetInt2d($this->_data, $this->_pos)) >> 4;
|
||||||
|
|
||||||
|
$length = $this->_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 = $this->_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 = $this->_GetInt2d($recordData, 2);
|
||||||
|
|
||||||
|
// offset: 4; size: 2; upper-left corner horizontal offset in 1/1024 of column width
|
||||||
|
$startOffsetX = $this->_GetInt2d($recordData, 4);
|
||||||
|
|
||||||
|
// offset: 6; size: 2; upper-left corner row index (0-based)
|
||||||
|
$r1 = $this->_GetInt2d($recordData, 6);
|
||||||
|
|
||||||
|
// offset: 8; size: 2; upper-left corner vertical offset in 1/256 of row height
|
||||||
|
$startOffsetY = $this->_GetInt2d($recordData, 8);
|
||||||
|
|
||||||
|
// offset: 10; size: 2; bottom-right corner column index (0-based)
|
||||||
|
$c2 = $this->_GetInt2d($recordData, 10);
|
||||||
|
|
||||||
|
// offset: 12; size: 2; bottom-right corner horizontal offset in 1/1024 of column width
|
||||||
|
$endOffsetX = $this->_GetInt2d($recordData, 12);
|
||||||
|
|
||||||
|
// offset: 14; size: 2; bottom-right corner row index (0-based)
|
||||||
|
$r2 = $this->_GetInt2d($recordData, 14);
|
||||||
|
|
||||||
|
// offset: 16; size: 2; bottom-right corner vertical offset in 1/256 of row height
|
||||||
|
$endOffsetY = $this->_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 = $this->_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 = $this->_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 = $this->_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read 16-bit unsigned integer
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @param int $pos
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function _GetInt2d($data, $pos)
|
||||||
|
{
|
||||||
|
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read 32-bit signed integer
|
||||||
|
*
|
||||||
|
* @param string $data
|
||||||
|
* @param int $pos
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function _GetInt4d($data, $pos)
|
||||||
|
{
|
||||||
|
//return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) |
|
||||||
|
// (ord($data[$pos + 2]) << 16) | (ord($data[$pos + 3]) << 24);
|
||||||
|
|
||||||
|
// FIX: represent numbers correctly on 64-bit system
|
||||||
|
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334
|
||||||
|
$_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,47 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_IReadFilter
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
interface PHPExcel_Reader_IReadFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Should this cell be read?
|
||||||
|
*
|
||||||
|
* @param $column String column index
|
||||||
|
* @param $row Row index
|
||||||
|
* @param $worksheetName Optional worksheet name
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function readCell($column, $row, $worksheetName = '');
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_IReader
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function load($pFilename);
|
||||||
|
}
|
|
@ -0,0 +1,507 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** PHPExcel root directory */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_OOCalc
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read data only?
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $_readDataOnly = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restict which sheets should be loaded?
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $_loadSheetsOnly = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sheet index to read
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_sheetIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $_styles = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_IReadFilter instance
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
private $_readFilter = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data only?
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getReadDataOnly() {
|
||||||
|
return $this->_readDataOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read data only
|
||||||
|
*
|
||||||
|
* @param boolean $pValue
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setReadDataOnly($pValue = false) {
|
||||||
|
$this->_readDataOnly = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get which sheets to load
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getLoadSheetsOnly()
|
||||||
|
{
|
||||||
|
return $this->_loadSheetsOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set which sheets to load
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setLoadSheetsOnly($value = null)
|
||||||
|
{
|
||||||
|
$this->_loadSheetsOnly = is_array($value) ?
|
||||||
|
$value : array($value);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all sheets to load
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setLoadAllSheets()
|
||||||
|
{
|
||||||
|
$this->_loadSheetsOnly = null;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read filter
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
public function getReadFilter() {
|
||||||
|
return $this->_readFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read filter
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Reader_IReadFilter $pValue
|
||||||
|
* @return PHPExcel_Reader_Excel2007
|
||||||
|
*/
|
||||||
|
public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) {
|
||||||
|
$this->_readFilter = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Reader_OOCalc
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->_sheetIndex = 0;
|
||||||
|
$this->_readFilter = new PHPExcel_Reader_DefaultReadFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the current PHPExcel_Reader_IReader read the file?
|
||||||
|
*
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canRead($pFilename)
|
||||||
|
{
|
||||||
|
// Check if zip class exists
|
||||||
|
if (!class_exists('ZipArchive')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load file
|
||||||
|
$zip = new ZipArchive;
|
||||||
|
if ($zip->open($pFilename) === true) {
|
||||||
|
// check if it is an OOXML archive
|
||||||
|
$mimeType = $zip->getFromName("mimetype");
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function load($pFilename)
|
||||||
|
{
|
||||||
|
// Create new PHPExcel
|
||||||
|
$objPHPExcel = new PHPExcel();
|
||||||
|
|
||||||
|
// Load into this instance
|
||||||
|
return $this->loadIntoExisting($pFilename, $objPHPExcel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) {
|
||||||
|
$styleAttributeValue = strtolower($styleAttributeValue);
|
||||||
|
foreach($styleList as $style) {
|
||||||
|
if ($styleAttributeValue == strtolower($style)) {
|
||||||
|
$styleAttributeValue = $style;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file into PHPExcel instance
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @param PHPExcel $objPHPExcel
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
|
||||||
|
{
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$timezoneObj = new DateTimeZone('Europe/London');
|
||||||
|
$GMT = new DateTimeZone('UTC');
|
||||||
|
|
||||||
|
$zip = new ZipArchive;
|
||||||
|
if ($zip->open($pFilename) === true) {
|
||||||
|
// echo '<h1>Meta Information</h1>';
|
||||||
|
$xml = simplexml_load_string($zip->getFromName("meta.xml"));
|
||||||
|
$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) {
|
||||||
|
// echo $propertyName.' = '.$propertyValue.'<hr />';
|
||||||
|
|
||||||
|
switch ($propertyName) {
|
||||||
|
case 'title' :
|
||||||
|
$docProps->setTitle($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'subject' :
|
||||||
|
$docProps->setSubject($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'creator' :
|
||||||
|
$docProps->setCreator($propertyValue);
|
||||||
|
break;
|
||||||
|
case 'date' :
|
||||||
|
$creationDate = strtotime($propertyValue);
|
||||||
|
$docProps->setCreated($creationDate);
|
||||||
|
break;
|
||||||
|
case 'description' :
|
||||||
|
$docProps->setDescription($propertyValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$officePropertyMeta = array();
|
||||||
|
if (isset($namespacesMeta['dc'])) {
|
||||||
|
$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
|
||||||
|
}
|
||||||
|
foreach($officePropertyMeta as $propertyName => $propertyValue) {
|
||||||
|
$propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']);
|
||||||
|
|
||||||
|
// echo $propertyName.' = '.$propertyValue.'<br />';
|
||||||
|
// foreach ($propertyValueAttributes as $key => $value) {
|
||||||
|
// echo $key.' = '.$value.'<br />';
|
||||||
|
// }
|
||||||
|
// echo '<hr />';
|
||||||
|
//
|
||||||
|
switch ($propertyName) {
|
||||||
|
case 'keyword' :
|
||||||
|
$docProps->setKeywords($propertyValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// echo '<h1>Workbook Content</h1>';
|
||||||
|
$xml = simplexml_load_string($zip->getFromName("content.xml"));
|
||||||
|
$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'];
|
||||||
|
$objPHPExcel->getActiveSheet()->setTitle($worksheetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$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' :
|
||||||
|
$columnID = 'A';
|
||||||
|
foreach($rowData as $key => $cellData) {
|
||||||
|
// echo '<b>'.$columnID.$rowID.'</b><br />';
|
||||||
|
$cellDataText = $cellData->children($namespacesContent['text']);
|
||||||
|
$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($cellDataText->p)) {
|
||||||
|
// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'<br />';
|
||||||
|
switch ($cellDataOfficeAttributes['value-type']) {
|
||||||
|
case 'string' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_STRING;
|
||||||
|
$dataValue = $cellDataText->p;
|
||||||
|
if (isset($dataValue->a)) {
|
||||||
|
$dataValue = $dataValue->a;
|
||||||
|
$cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']);
|
||||||
|
$hyperlink = $cellXLinkAttributes['href'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'boolean' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_BOOL;
|
||||||
|
$dataValue = ($cellDataText->p == 'TRUE') ? True : False;
|
||||||
|
break;
|
||||||
|
case 'float' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
|
||||||
|
$dataValue = (float) $cellDataOfficeAttributes['value'];
|
||||||
|
if (floor($dataValue) == $dataValue) {
|
||||||
|
$dataValue = (integer) $dataValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'date' :
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
|
||||||
|
$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 (!is_null($hyperlink)) {
|
||||||
|
// echo 'Hyperlink is '.$hyperlink.'<br />';
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($hasCalculatedValue) {
|
||||||
|
$type = PHPExcel_Cell_DataType::TYPE_FORMULA;
|
||||||
|
// echo 'Formula: '.$cellDataFormula.'<br />';
|
||||||
|
$cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1);
|
||||||
|
$temp = explode('"',$cellDataFormula);
|
||||||
|
foreach($temp as $key => &$value) {
|
||||||
|
// Only replace in alternate array entries (i.e. non-quoted blocks)
|
||||||
|
if (($key % 2) == 0) {
|
||||||
|
$value = preg_replace('/\[\.(.*):\.(.*)\]/Ui','$1:$2',$value);
|
||||||
|
$value = preg_replace('/\[\.(.*)\]/Ui','$1',$value);
|
||||||
|
$value = PHPExcel_Calculation::_translateSeparator(';',',',$value,$inBraces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($value);
|
||||||
|
// Then rebuild the formula string
|
||||||
|
$cellDataFormula = implode('"',$temp);
|
||||||
|
// echo 'Adjusted Formula: '.$cellDataFormula.'<br />';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_null($type)) {
|
||||||
|
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type);
|
||||||
|
if ($hasCalculatedValue) {
|
||||||
|
// echo 'Forumla result is '.$dataValue.'<br />';
|
||||||
|
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($dataValue);
|
||||||
|
}
|
||||||
|
if (($cellDataOfficeAttributes['value-type'] == 'date') ||
|
||||||
|
($cellDataOfficeAttributes['value-type'] == 'time')) {
|
||||||
|
$objPHPExcel->getActiveSheet()->getStyle($columnID.$rowID)->getNumberFormat()->setFormatCode($formatting);
|
||||||
|
}
|
||||||
|
if (!is_null($hyperlink)) {
|
||||||
|
$objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->getHyperlink()->setUrl($hyperlink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merged cells
|
||||||
|
if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) {
|
||||||
|
$columnTo = $columnID;
|
||||||
|
if (isset($cellDataTableAttributes['number-columns-spanned'])) {
|
||||||
|
$columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2);
|
||||||
|
}
|
||||||
|
$rowTo = $rowID;
|
||||||
|
if (isset($cellDataTableAttributes['number-rows-spanned'])) {
|
||||||
|
$rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1;
|
||||||
|
}
|
||||||
|
$cellRange = $columnID.$rowID.':'.$columnTo.$rowTo;
|
||||||
|
$objPHPExcel->getActiveSheet()->mergeCells($cellRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($cellDataTableAttributes['number-columns-repeated'])) {
|
||||||
|
// echo 'Repeated '.$cellDataTableAttributes['number-columns-repeated'].' times<br />';
|
||||||
|
$columnID = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-repeated'] - 2);
|
||||||
|
}
|
||||||
|
++$columnID;
|
||||||
|
}
|
||||||
|
++$rowID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++$worksheetID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return $objPHPExcel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet index
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getSheetIndex() {
|
||||||
|
return $this->_sheetIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sheet index
|
||||||
|
*
|
||||||
|
* @param int $pValue Sheet index
|
||||||
|
* @return PHPExcel_Reader_OOCalc
|
||||||
|
*/
|
||||||
|
public function setSheetIndex($pValue = 0) {
|
||||||
|
$this->_sheetIndex = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,509 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** PHPExcel root directory */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_SYLK
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Input encoding
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_inputEncoding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delimiter
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_delimiter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enclosure
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_enclosure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Line ending
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_lineEnding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sheet index to read
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_sheetIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $_formats = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format Count
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $_format = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_IReadFilter instance
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
private $_readFilter = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_Reader_SYLK
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->_inputEncoding = 'ANSI';
|
||||||
|
$this->_delimiter = ';';
|
||||||
|
$this->_enclosure = '"';
|
||||||
|
$this->_lineEnding = PHP_EOL;
|
||||||
|
$this->_sheetIndex = 0;
|
||||||
|
$this->_readFilter = new PHPExcel_Reader_DefaultReadFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can the current PHPExcel_Reader_IReader read the file?
|
||||||
|
*
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canRead($pFilename)
|
||||||
|
{
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read sample data (first 2 KB will do)
|
||||||
|
$fh = fopen($pFilename, 'r');
|
||||||
|
$data = fread($fh, 2048);
|
||||||
|
fclose($fh);
|
||||||
|
|
||||||
|
// Count delimiters in file
|
||||||
|
$delimiterCount = substr_count($data, ';');
|
||||||
|
if ($delimiterCount < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Analyze first line looking for ID; signature
|
||||||
|
$lines = explode("\n", $data);
|
||||||
|
if (substr($lines[0],0,4) != 'ID;P') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function load($pFilename)
|
||||||
|
{
|
||||||
|
// Create new PHPExcel
|
||||||
|
$objPHPExcel = new PHPExcel();
|
||||||
|
|
||||||
|
// Load into this instance
|
||||||
|
return $this->loadIntoExisting($pFilename, $objPHPExcel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read filter
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Reader_IReadFilter
|
||||||
|
*/
|
||||||
|
public function getReadFilter() {
|
||||||
|
return $this->_readFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read filter
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Reader_IReadFilter $pValue
|
||||||
|
*/
|
||||||
|
public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) {
|
||||||
|
$this->_readFilter = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel from file into PHPExcel instance
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @param PHPExcel $objPHPExcel
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
|
||||||
|
{
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new PHPExcel
|
||||||
|
while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) {
|
||||||
|
$objPHPExcel->createSheet();
|
||||||
|
}
|
||||||
|
$objPHPExcel->setActiveSheetIndex( $this->_sheetIndex );
|
||||||
|
|
||||||
|
$fromFormats = array('\-', '\ ');
|
||||||
|
$toFormats = array('-', ' ');
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
$fileHandle = fopen($pFilename, 'r');
|
||||||
|
if ($fileHandle === false) {
|
||||||
|
throw new Exception("Could not open file $pFilename for reading.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through file
|
||||||
|
$rowData = array();
|
||||||
|
$column = $row = '';
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
foreach($temp as $key => &$value) {
|
||||||
|
// Only count/replace in alternate array entries
|
||||||
|
if (($key % 2) == 0) {
|
||||||
|
preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE);
|
||||||
|
// Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way
|
||||||
|
// through the formula from left to right. Reversing means that we work right to left.through
|
||||||
|
// the formula
|
||||||
|
$cellReferences = array_reverse($cellReferences);
|
||||||
|
// Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
|
||||||
|
// then modify the formula to use that new reference
|
||||||
|
foreach($cellReferences as $cellReference) {
|
||||||
|
$rowReference = $cellReference[2][0];
|
||||||
|
// Empty R reference is the current row
|
||||||
|
if ($rowReference == '') $rowReference = $row;
|
||||||
|
// Bracketed R references are relative to the current row
|
||||||
|
if ($rowReference{0} == '[') $rowReference = $row + trim($rowReference,'[]');
|
||||||
|
$columnReference = $cellReference[4][0];
|
||||||
|
// Empty C reference is the current column
|
||||||
|
if ($columnReference == '') $columnReference = $column;
|
||||||
|
// Bracketed C references are relative to the current column
|
||||||
|
if ($columnReference{0} == '[') $columnReference = $column + trim($columnReference,'[]');
|
||||||
|
$A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference;
|
||||||
|
|
||||||
|
$value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($value);
|
||||||
|
// Then rebuild the formula string
|
||||||
|
$cellDataFormula = implode('"',$temp);
|
||||||
|
$hasCalculatedValue = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1);
|
||||||
|
$cellData = PHPExcel_Calculation::_unwrapResult($cellData);
|
||||||
|
|
||||||
|
// Set cell value
|
||||||
|
$objPHPExcel->getActiveSheet()->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);
|
||||||
|
$objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]);
|
||||||
|
}
|
||||||
|
if ((count($styleData) > 0) && ($column > '') && ($row > '')) {
|
||||||
|
$columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1);
|
||||||
|
$objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($styleData);
|
||||||
|
}
|
||||||
|
if ($columnWidth > '') {
|
||||||
|
if ($startCol == $endCol) {
|
||||||
|
$startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1);
|
||||||
|
$objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth);
|
||||||
|
} else {
|
||||||
|
$startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1);
|
||||||
|
$endCol = PHPExcel_Cell::stringFromColumnIndex($endCol-1);
|
||||||
|
$objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth);
|
||||||
|
do {
|
||||||
|
$objPHPExcel->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth);
|
||||||
|
} while ($startCol != $endCol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach($rowData as $rowDatum) {
|
||||||
|
switch($rowDatum{0}) {
|
||||||
|
case 'C' :
|
||||||
|
case 'X' : $column = substr($rowDatum,1);
|
||||||
|
break;
|
||||||
|
case 'R' :
|
||||||
|
case 'Y' : $row = substr($rowDatum,1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close file
|
||||||
|
fclose($fileHandle);
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return $objPHPExcel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get delimiter
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDelimiter() {
|
||||||
|
return $this->_delimiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set delimiter
|
||||||
|
*
|
||||||
|
* @param string $pValue Delimiter, defaults to ,
|
||||||
|
* @return PHPExcel_Reader_SYLK
|
||||||
|
*/
|
||||||
|
public function setDelimiter($pValue = ',') {
|
||||||
|
$this->_delimiter = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get enclosure
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEnclosure() {
|
||||||
|
return $this->_enclosure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set enclosure
|
||||||
|
*
|
||||||
|
* @param string $pValue Enclosure, defaults to "
|
||||||
|
* @return PHPExcel_Reader_SYLK
|
||||||
|
*/
|
||||||
|
public function setEnclosure($pValue = '"') {
|
||||||
|
if ($pValue == '') {
|
||||||
|
$pValue = '"';
|
||||||
|
}
|
||||||
|
$this->_enclosure = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get line ending
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLineEnding() {
|
||||||
|
return $this->_lineEnding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set line ending
|
||||||
|
*
|
||||||
|
* @param string $pValue Line ending, defaults to OS line ending (PHP_EOL)
|
||||||
|
* @return PHPExcel_Reader_SYLK
|
||||||
|
*/
|
||||||
|
public function setLineEnding($pValue = PHP_EOL) {
|
||||||
|
$this->_lineEnding = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sheet index
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getSheetIndex() {
|
||||||
|
return $this->_sheetIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sheet index
|
||||||
|
*
|
||||||
|
* @param int $pValue Sheet index
|
||||||
|
* @return PHPExcel_Reader_SYLK
|
||||||
|
*/
|
||||||
|
public function setSheetIndex($pValue = 0) {
|
||||||
|
$this->_sheetIndex = $pValue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** PHPExcel root directory */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Reader_Serialized
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Reader
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Reader_Serialized implements PHPExcel_Reader_IReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Can the current PHPExcel_Reader_IReader read the file?
|
||||||
|
*
|
||||||
|
* @param string $pFileName
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function canRead($pFilename)
|
||||||
|
{
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fileSupportsUnserializePHPExcel($pFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads PHPExcel Serialized file
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @return PHPExcel
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function load($pFilename)
|
||||||
|
{
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unserialize... First make sure the file supports it!
|
||||||
|
if (!$this->fileSupportsUnserializePHPExcel($pFilename)) {
|
||||||
|
throw new Exception("Invalid file format for PHPExcel_Reader_Serialized: " . $pFilename . ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_loadSerialized($pFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load PHPExcel Serialized file
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @return PHPExcel
|
||||||
|
*/
|
||||||
|
private function _loadSerialized($pFilename) {
|
||||||
|
$xmlData = simplexml_load_string(file_get_contents("zip://$pFilename#phpexcel.xml"));
|
||||||
|
$excel = unserialize(base64_decode((string)$xmlData->data));
|
||||||
|
|
||||||
|
// Update media links
|
||||||
|
for ($i = 0; $i < $excel->getSheetCount(); ++$i) {
|
||||||
|
for ($j = 0; $j < $excel->getSheet($i)->getDrawingCollection()->count(); ++$j) {
|
||||||
|
if ($excel->getSheet($i)->getDrawingCollection()->offsetGet($j) instanceof PHPExcl_Worksheet_BaseDrawing) {
|
||||||
|
$imgTemp =& $excel->getSheet($i)->getDrawingCollection()->offsetGet($j);
|
||||||
|
$imgTemp->setPath('zip://' . $pFilename . '#media/' . $imgTemp->getFilename(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $excel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does a file support UnserializePHPExcel ?
|
||||||
|
*
|
||||||
|
* @param string $pFilename
|
||||||
|
* @throws Exception
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function fileSupportsUnserializePHPExcel($pFilename = '') {
|
||||||
|
// Check if file exists
|
||||||
|
if (!file_exists($pFilename)) {
|
||||||
|
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// File exists, does it contain phpexcel.xml?
|
||||||
|
return PHPExcel_Shared_File::file_exists("zip://$pFilename#phpexcel.xml");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,614 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_ReferenceHelper (Singleton)
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_ReferenceHelper
|
||||||
|
{
|
||||||
|
/** Constants */
|
||||||
|
/** Regular Expressions */
|
||||||
|
const REFHELPER_REGEXP_CELLREF = '((\w*|\'[^!]*\')!)?(?<![:a-z\$])(\$?[a-z]{1,3}\$?\d+)(?=[^:!\d\'])';
|
||||||
|
const REFHELPER_REGEXP_CELLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}\$?\d+):(\$?[a-z]{1,3}\$?\d+)';
|
||||||
|
const REFHELPER_REGEXP_ROWRANGE = '((\w*|\'[^!]*\')!)?(\$?\d+):(\$?\d+)';
|
||||||
|
const REFHELPER_REGEXP_COLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}):(\$?[a-z]{1,3})';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of this class
|
||||||
|
*
|
||||||
|
* @var PHPExcel_ReferenceHelper
|
||||||
|
*/
|
||||||
|
private static $_instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an instance of this class
|
||||||
|
*
|
||||||
|
* @return PHPExcel_ReferenceHelper
|
||||||
|
*/
|
||||||
|
public static function getInstance() {
|
||||||
|
if (!isset(self::$_instance) || is_null(self::$_instance)) {
|
||||||
|
self::$_instance = new PHPExcel_ReferenceHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_ReferenceHelper
|
||||||
|
*/
|
||||||
|
protected function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new column, updating all possible related data
|
||||||
|
*
|
||||||
|
* @param int $pBefore Insert before this one
|
||||||
|
* @param int $pNumCols Number of columns to insert
|
||||||
|
* @param int $pNumRows Number of rows to insert
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) {
|
||||||
|
$aCellCollection = $pSheet->getCellCollection();
|
||||||
|
|
||||||
|
// Get coordinates of $pBefore
|
||||||
|
$beforeColumn = 'A';
|
||||||
|
$beforeRow = 1;
|
||||||
|
list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore );
|
||||||
|
|
||||||
|
|
||||||
|
// Clear cells if we are removing columns or rows
|
||||||
|
$highestColumn = $pSheet->getHighestColumn();
|
||||||
|
$highestRow = $pSheet->getHighestRow();
|
||||||
|
|
||||||
|
// 1. Clear column strips if we are removing columns
|
||||||
|
if ($pNumCols < 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols > 0) {
|
||||||
|
for ($i = 1; $i <= $highestRow - 1; ++$i) {
|
||||||
|
for ($j = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1 + $pNumCols; $j <= PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2; ++$j) {
|
||||||
|
$coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i;
|
||||||
|
$pSheet->removeConditionalStyles($coordinate);
|
||||||
|
if ($pSheet->cellExists($coordinate)) {
|
||||||
|
$pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL);
|
||||||
|
$pSheet->getCell($coordinate)->setXfIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Clear row strips if we are removing rows
|
||||||
|
if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) {
|
||||||
|
for ($i = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) {
|
||||||
|
for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) {
|
||||||
|
$coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j;
|
||||||
|
$pSheet->removeConditionalStyles($coordinate);
|
||||||
|
if ($pSheet->cellExists($coordinate)) {
|
||||||
|
$pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL);
|
||||||
|
$pSheet->getCell($coordinate)->setXfIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Loop through cells, bottom-up, and change cell coordinates
|
||||||
|
while (($cellID = ($pNumCols < 0 || $pNumRows < 0) ? array_shift($aCellCollection) : array_pop($aCellCollection))) {
|
||||||
|
$cell = $pSheet->getCell($cellID);
|
||||||
|
|
||||||
|
// New coordinates
|
||||||
|
$newCoordinates = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1 + $pNumCols ) . ($cell->getRow() + $pNumRows);
|
||||||
|
|
||||||
|
// Should the cell be updated? Move value and cellXf index from one cell to another.
|
||||||
|
if ((PHPExcel_Cell::columnIndexFromString( $cell->getColumn() ) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)) &&
|
||||||
|
($cell->getRow() >= $beforeRow)) {
|
||||||
|
|
||||||
|
// Update cell styles
|
||||||
|
$pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex());
|
||||||
|
$cell->setXfIndex(0);
|
||||||
|
|
||||||
|
// Insert this cell at its new location
|
||||||
|
if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) {
|
||||||
|
// Formula should be adjusted
|
||||||
|
$pSheet->getCell($newCoordinates)
|
||||||
|
->setValue($this->updateFormulaReferences($cell->getValue(), $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle()));
|
||||||
|
} else {
|
||||||
|
// Formula should not be adjusted
|
||||||
|
$pSheet->getCell($newCoordinates)->setValue($cell->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the original cell
|
||||||
|
$pSheet->getCell($cell->getCoordinate())->setValue('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Duplicate styles for the newly inserted cells
|
||||||
|
$highestColumn = $pSheet->getHighestColumn();
|
||||||
|
$highestRow = $pSheet->getHighestRow();
|
||||||
|
|
||||||
|
if ($pNumCols > 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 > 0) {
|
||||||
|
for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) {
|
||||||
|
|
||||||
|
// Style
|
||||||
|
$coordinate = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 ) . $i;
|
||||||
|
if ($pSheet->cellExists($coordinate)) {
|
||||||
|
$xfIndex = $pSheet->getCell($coordinate)->getXfIndex();
|
||||||
|
$conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ?
|
||||||
|
$pSheet->getConditionalStyles($coordinate) : false;
|
||||||
|
for ($j = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $j <= PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols; ++$j) {
|
||||||
|
$pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex);
|
||||||
|
if ($conditionalStyles) {
|
||||||
|
$cloned = array();
|
||||||
|
foreach ($conditionalStyles as $conditionalStyle) {
|
||||||
|
$cloned[] = clone $conditionalStyle;
|
||||||
|
}
|
||||||
|
$pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pNumRows > 0 && $beforeRow - 1 > 0) {
|
||||||
|
for ($i = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) {
|
||||||
|
|
||||||
|
// Style
|
||||||
|
$coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1);
|
||||||
|
if ($pSheet->cellExists($coordinate)) {
|
||||||
|
$xfIndex = $pSheet->getCell($coordinate)->getXfIndex();
|
||||||
|
$conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ?
|
||||||
|
$pSheet->getConditionalStyles($coordinate) : false;
|
||||||
|
for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) {
|
||||||
|
$pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex);
|
||||||
|
if ($conditionalStyles) {
|
||||||
|
$cloned = array();
|
||||||
|
foreach ($conditionalStyles as $conditionalStyle) {
|
||||||
|
$cloned[] = clone $conditionalStyle;
|
||||||
|
}
|
||||||
|
$pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: column dimensions
|
||||||
|
$aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true);
|
||||||
|
if (count($aColumnDimensions) > 0) {
|
||||||
|
foreach ($aColumnDimensions as $objColumnDimension) {
|
||||||
|
$newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows);
|
||||||
|
list($newReference) = PHPExcel_Cell::coordinateFromString($newReference);
|
||||||
|
if ($objColumnDimension->getColumnIndex() != $newReference) {
|
||||||
|
$objColumnDimension->setColumnIndex($newReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$pSheet->refreshColumnDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: row dimensions
|
||||||
|
$aRowDimensions = array_reverse($pSheet->getRowDimensions(), true);
|
||||||
|
if (count($aRowDimensions) > 0) {
|
||||||
|
foreach ($aRowDimensions as $objRowDimension) {
|
||||||
|
$newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows);
|
||||||
|
list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference);
|
||||||
|
if ($objRowDimension->getRowIndex() != $newReference) {
|
||||||
|
$objRowDimension->setRowIndex($newReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$pSheet->refreshRowDimensions();
|
||||||
|
|
||||||
|
$copyDimension = $pSheet->getRowDimension($beforeRow - 1);
|
||||||
|
for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) {
|
||||||
|
$newDimension = $pSheet->getRowDimension($i);
|
||||||
|
$newDimension->setRowHeight($copyDimension->getRowHeight());
|
||||||
|
$newDimension->setVisible($copyDimension->getVisible());
|
||||||
|
$newDimension->setOutlineLevel($copyDimension->getOutlineLevel());
|
||||||
|
$newDimension->setCollapsed($copyDimension->getCollapsed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: breaks
|
||||||
|
$aBreaks = array_reverse($pSheet->getBreaks(), true);
|
||||||
|
foreach ($aBreaks as $key => $value) {
|
||||||
|
$newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
if ($key != $newReference) {
|
||||||
|
$pSheet->setBreak( $newReference, $value );
|
||||||
|
$pSheet->setBreak( $key, PHPExcel_Worksheet::BREAK_NONE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: hyperlinks
|
||||||
|
$aHyperlinkCollection = array_reverse($pSheet->getHyperlinkCollection(), true);
|
||||||
|
foreach ($aHyperlinkCollection as $key => $value) {
|
||||||
|
$newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
if ($key != $newReference) {
|
||||||
|
$pSheet->setHyperlink( $newReference, $value );
|
||||||
|
$pSheet->setHyperlink( $key, null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: data validations
|
||||||
|
$aDataValidationCollection = array_reverse($pSheet->getDataValidationCollection(), true);
|
||||||
|
foreach ($aDataValidationCollection as $key => $value) {
|
||||||
|
$newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
if ($key != $newReference) {
|
||||||
|
$pSheet->setDataValidation( $newReference, $value );
|
||||||
|
$pSheet->setDataValidation( $key, null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: merge cells
|
||||||
|
$aMergeCells = $pSheet->getMergeCells();
|
||||||
|
$aNewMergeCells = array(); // the new array of all merge cells
|
||||||
|
foreach ($aMergeCells as $key => &$value) {
|
||||||
|
$newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
$aNewMergeCells[$newReference] = $newReference;
|
||||||
|
}
|
||||||
|
$pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: protected cells
|
||||||
|
$aProtectedCells = array_reverse($pSheet->getProtectedCells(), true);
|
||||||
|
foreach ($aProtectedCells as $key => $value) {
|
||||||
|
$newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
if ($key != $newReference) {
|
||||||
|
$pSheet->protectCells( $newReference, $value, true );
|
||||||
|
$pSheet->unprotectCells( $key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: autofilter
|
||||||
|
if ($pSheet->getAutoFilter() != '') {
|
||||||
|
$pSheet->setAutoFilter( $this->updateCellReference($pSheet->getAutoFilter(), $pBefore, $pNumCols, $pNumRows) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: freeze pane
|
||||||
|
if ($pSheet->getFreezePane() != '') {
|
||||||
|
$pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Page setup
|
||||||
|
if ($pSheet->getPageSetup()->isPrintAreaSet()) {
|
||||||
|
$pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update worksheet: drawings
|
||||||
|
$aDrawings = $pSheet->getDrawingCollection();
|
||||||
|
foreach ($aDrawings as $objDrawing) {
|
||||||
|
$newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows);
|
||||||
|
if ($objDrawing->getCoordinates() != $newReference) {
|
||||||
|
$objDrawing->setCoordinates($newReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update workbook: named ranges
|
||||||
|
if (count($pSheet->getParent()->getNamedRanges()) > 0) {
|
||||||
|
foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) {
|
||||||
|
if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) {
|
||||||
|
$namedRange->setRange(
|
||||||
|
$this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Garbage collect
|
||||||
|
$pSheet->garbageCollect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update references within formulas
|
||||||
|
*
|
||||||
|
* @param string $pFormula Formula to update
|
||||||
|
* @param int $pBefore Insert before this one
|
||||||
|
* @param int $pNumCols Number of columns to insert
|
||||||
|
* @param int $pNumRows Number of rows to insert
|
||||||
|
* @return string Updated formula
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, $sheetName = '') {
|
||||||
|
// Update cell references in the formula
|
||||||
|
$formulaBlocks = explode('"',$pFormula);
|
||||||
|
foreach($formulaBlocks as $i => &$formulaBlock) {
|
||||||
|
// Ignore blocks that were enclosed in quotes (even entries in the $formulaBlocks array after the explode)
|
||||||
|
if (($i % 2) == 0) {
|
||||||
|
$adjustCount = 0;
|
||||||
|
$newCellTokens = $cellTokens = array();
|
||||||
|
// Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5)
|
||||||
|
$matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_ROWRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER);
|
||||||
|
if ($matchCount > 0) {
|
||||||
|
foreach($matches as $match) {
|
||||||
|
$fromString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$fromString .= $match[3].':'.$match[4];
|
||||||
|
$modified3 = substr($this->updateCellReference('$A'.$match[3],$pBefore,$pNumCols,$pNumRows),2);
|
||||||
|
$modified4 = substr($this->updateCellReference('$A'.$match[4],$pBefore,$pNumCols,$pNumRows),2);
|
||||||
|
|
||||||
|
if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) {
|
||||||
|
if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
|
||||||
|
$toString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$toString .= $modified3.':'.$modified4;
|
||||||
|
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||||
|
$column = 100000;
|
||||||
|
$row = 10000000+trim($match[3],'$');
|
||||||
|
$cellIndex = $column.$row;
|
||||||
|
|
||||||
|
$newCellTokens[$cellIndex] = preg_quote($toString);
|
||||||
|
$cellTokens[$cellIndex] = '/(?<!\d)'.preg_quote($fromString).'(?!\d)/i';
|
||||||
|
++$adjustCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Search for column ranges (e.g. 'Sheet1'!C:E or C:E) with or without $ absolutes (e.g. $C:E)
|
||||||
|
$matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_COLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER);
|
||||||
|
if ($matchCount > 0) {
|
||||||
|
foreach($matches as $match) {
|
||||||
|
$fromString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$fromString .= $match[3].':'.$match[4];
|
||||||
|
$modified3 = substr($this->updateCellReference($match[3].'$1',$pBefore,$pNumCols,$pNumRows),0,-2);
|
||||||
|
$modified4 = substr($this->updateCellReference($match[4].'$1',$pBefore,$pNumCols,$pNumRows),0,-2);
|
||||||
|
|
||||||
|
if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) {
|
||||||
|
if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
|
||||||
|
$toString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$toString .= $modified3.':'.$modified4;
|
||||||
|
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||||
|
$column = PHPExcel_Cell::columnIndexFromString(trim($match[3],'$')) + 100000;
|
||||||
|
$row = 10000000;
|
||||||
|
$cellIndex = $column.$row;
|
||||||
|
|
||||||
|
$newCellTokens[$cellIndex] = preg_quote($toString);
|
||||||
|
$cellTokens[$cellIndex] = '/(?<![A-Z])'.preg_quote($fromString).'(?![A-Z])/i';
|
||||||
|
++$adjustCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Search for cell ranges (e.g. 'Sheet1'!A3:C5 or A3:C5) with or without $ absolutes (e.g. $A1:C$5)
|
||||||
|
$matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER);
|
||||||
|
if ($matchCount > 0) {
|
||||||
|
foreach($matches as $match) {
|
||||||
|
$fromString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$fromString .= $match[3].':'.$match[4];
|
||||||
|
$modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows);
|
||||||
|
$modified4 = $this->updateCellReference($match[4],$pBefore,$pNumCols,$pNumRows);
|
||||||
|
|
||||||
|
if ($match[3].$match[4] !== $modified3.$modified4) {
|
||||||
|
if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
|
||||||
|
$toString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$toString .= $modified3.':'.$modified4;
|
||||||
|
list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]);
|
||||||
|
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||||
|
$column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000;
|
||||||
|
$row = trim($row,'$') + 10000000;
|
||||||
|
$cellIndex = $column.$row;
|
||||||
|
|
||||||
|
$newCellTokens[$cellIndex] = preg_quote($toString);
|
||||||
|
$cellTokens[$cellIndex] = '/(?<![A-Z])'.preg_quote($fromString).'(?!\d)/i';
|
||||||
|
++$adjustCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Search for cell references (e.g. 'Sheet1'!A3 or C5) with or without $ absolutes (e.g. $A1 or C$5)
|
||||||
|
$matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLREF.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER);
|
||||||
|
if ($matchCount > 0) {
|
||||||
|
foreach($matches as $match) {
|
||||||
|
$fromString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$fromString .= $match[3];
|
||||||
|
$modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows);
|
||||||
|
|
||||||
|
if ($match[3] !== $modified3) {
|
||||||
|
if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
|
||||||
|
$toString = ($match[2] > '') ? $match[2].'!' : '';
|
||||||
|
$toString .= $modified3;
|
||||||
|
list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]);
|
||||||
|
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||||
|
$column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000;
|
||||||
|
$row = trim($row,'$') + 10000000;
|
||||||
|
$cellIndex = $column.$row;
|
||||||
|
|
||||||
|
$newCellTokens[$cellIndex] = preg_quote($toString);
|
||||||
|
$cellTokens[$cellIndex] = '/(?<![A-Z])'.preg_quote($fromString).'(?!\d)/i';
|
||||||
|
++$adjustCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($adjustCount > 0) {
|
||||||
|
krsort($cellTokens);
|
||||||
|
krsort($newCellTokens);
|
||||||
|
// Update cell references in the formula
|
||||||
|
$formulaBlock = str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($formulaBlock);
|
||||||
|
|
||||||
|
// Then rebuild the formula string
|
||||||
|
return implode('"',$formulaBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update cell reference
|
||||||
|
*
|
||||||
|
* @param string $pCellRange Cell range
|
||||||
|
* @param int $pBefore Insert before this one
|
||||||
|
* @param int $pNumCols Number of columns to increment
|
||||||
|
* @param int $pNumRows Number of rows to increment
|
||||||
|
* @return string Updated cell range
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) {
|
||||||
|
// Is it in another worksheet? Will not have to update anything.
|
||||||
|
if (strpos($pCellRange, "!") !== false) {
|
||||||
|
return $pCellRange;
|
||||||
|
// Is it a range or a single cell?
|
||||||
|
} elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) {
|
||||||
|
// Single cell
|
||||||
|
return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
} elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) {
|
||||||
|
// Range
|
||||||
|
return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
} else {
|
||||||
|
// Return original
|
||||||
|
return $pCellRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update named formulas (i.e. containing worksheet references / named ranges)
|
||||||
|
*
|
||||||
|
* @param PHPExcel $pPhpExcel Object to update
|
||||||
|
* @param string $oldName Old name (name to replace)
|
||||||
|
* @param string $newName New name
|
||||||
|
*/
|
||||||
|
public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') {
|
||||||
|
if ($oldName == '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($pPhpExcel->getWorksheetIterator() as $sheet) {
|
||||||
|
foreach ($sheet->getCellCollection(false) as $cellID) {
|
||||||
|
$cell = $sheet->getCell($cellID);
|
||||||
|
if (!is_null($cell) && $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) {
|
||||||
|
$formula = $cell->getValue();
|
||||||
|
if (strpos($formula, $oldName) !== false) {
|
||||||
|
$formula = str_replace("'" . $oldName . "'!", "'" . $newName . "'!", $formula);
|
||||||
|
$formula = str_replace($oldName . "!", $newName . "!", $formula);
|
||||||
|
$cell->setValueExplicit($formula, PHPExcel_Cell_DataType::TYPE_FORMULA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update cell range
|
||||||
|
*
|
||||||
|
* @param string $pCellRange Cell range
|
||||||
|
* @param int $pBefore Insert before this one
|
||||||
|
* @param int $pNumCols Number of columns to increment
|
||||||
|
* @param int $pNumRows Number of rows to increment
|
||||||
|
* @return string Updated cell range
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) {
|
||||||
|
if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) {
|
||||||
|
// Update range
|
||||||
|
$range = PHPExcel_Cell::splitRange($pCellRange);
|
||||||
|
for ($i = 0; $i < count($range); ++$i) {
|
||||||
|
for ($j = 0; $j < count($range[$i]); ++$j) {
|
||||||
|
$range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate range string
|
||||||
|
return PHPExcel_Cell::buildRange($range);
|
||||||
|
} else {
|
||||||
|
throw new Exception("Only cell ranges may be passed to this method.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update single cell reference
|
||||||
|
*
|
||||||
|
* @param string $pCellReference Single cell reference
|
||||||
|
* @param int $pBefore Insert before this one
|
||||||
|
* @param int $pNumCols Number of columns to increment
|
||||||
|
* @param int $pNumRows Number of rows to increment
|
||||||
|
* @return string Updated cell reference
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) {
|
||||||
|
if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) {
|
||||||
|
// Get coordinates of $pBefore
|
||||||
|
$beforeColumn = 'A';
|
||||||
|
$beforeRow = 1;
|
||||||
|
list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore );
|
||||||
|
|
||||||
|
// Get coordinates
|
||||||
|
$newColumn = 'A';
|
||||||
|
$newRow = 1;
|
||||||
|
list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference );
|
||||||
|
|
||||||
|
// Make sure the reference can be used
|
||||||
|
if ($newColumn == '' && $newRow == '')
|
||||||
|
{
|
||||||
|
return $pCellReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify which parts should be updated
|
||||||
|
$updateColumn = (PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn))
|
||||||
|
&& (strpos($newColumn, '$') === false)
|
||||||
|
&& (strpos($beforeColumn, '$') === false);
|
||||||
|
|
||||||
|
$updateRow = ($newRow >= $beforeRow)
|
||||||
|
&& (strpos($newRow, '$') === false)
|
||||||
|
&& (strpos($beforeRow, '$') === false);
|
||||||
|
|
||||||
|
// Create new column reference
|
||||||
|
if ($updateColumn) {
|
||||||
|
$newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new row reference
|
||||||
|
if ($updateRow) {
|
||||||
|
$newRow = $newRow + $pNumRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return new reference
|
||||||
|
return $newColumn . $newRow;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Only single cell references may be passed to this method.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __clone implementation. Cloning should not be allowed in a Singleton!
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public final function __clone() {
|
||||||
|
throw new Exception("Cloning a Singleton is not allowed!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_RichText
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_RichText implements PHPExcel_IComparable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Rich text elements
|
||||||
|
*
|
||||||
|
* @var PHPExcel_RichText_ITextElement[]
|
||||||
|
*/
|
||||||
|
private $_richTextElements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_RichText instance
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $pParent
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function __construct(PHPExcel_Cell $pCell = null)
|
||||||
|
{
|
||||||
|
// Initialise variables
|
||||||
|
$this->_richTextElements = array();
|
||||||
|
|
||||||
|
// Rich-Text string attached to cell?
|
||||||
|
if (!is_null($pCell)) {
|
||||||
|
// Add cell text and style
|
||||||
|
if ($pCell->getValue() != "") {
|
||||||
|
$objRun = new PHPExcel_RichText_Run($pCell->getValue());
|
||||||
|
$objRun->setFont(clone $pCell->getParent()->getStyle($pCell->getCoordinate())->getFont());
|
||||||
|
$this->addText($objRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set parent value
|
||||||
|
$pCell->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add text
|
||||||
|
*
|
||||||
|
* @param PHPExcel_RichText_ITextElement $pText Rich text element
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_RichText
|
||||||
|
*/
|
||||||
|
public function addText(PHPExcel_RichText_ITextElement $pText = null)
|
||||||
|
{
|
||||||
|
$this->_richTextElements[] = $pText;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create text
|
||||||
|
*
|
||||||
|
* @param string $pText Text
|
||||||
|
* @return PHPExcel_RichText_TextElement
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function createText($pText = '')
|
||||||
|
{
|
||||||
|
$objText = new PHPExcel_RichText_TextElement($pText);
|
||||||
|
$this->addText($objText);
|
||||||
|
return $objText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create text run
|
||||||
|
*
|
||||||
|
* @param string $pText Text
|
||||||
|
* @return PHPExcel_RichText_Run
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function createTextRun($pText = '')
|
||||||
|
{
|
||||||
|
$objText = new PHPExcel_RichText_Run($pText);
|
||||||
|
$this->addText($objText);
|
||||||
|
return $objText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plain text
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPlainText()
|
||||||
|
{
|
||||||
|
// Return value
|
||||||
|
$returnValue = '';
|
||||||
|
|
||||||
|
// Loop through all PHPExcel_RichText_ITextElement
|
||||||
|
foreach ($this->_richTextElements as $text) {
|
||||||
|
$returnValue .= $text->getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return $returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert to string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString() {
|
||||||
|
return $this->getPlainText();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Rich Text elements
|
||||||
|
*
|
||||||
|
* @return PHPExcel_RichText_ITextElement[]
|
||||||
|
*/
|
||||||
|
public function getRichTextElements()
|
||||||
|
{
|
||||||
|
return $this->_richTextElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Rich Text elements
|
||||||
|
*
|
||||||
|
* @param PHPExcel_RichText_ITextElement[] $pElements Array of elements
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_RichText
|
||||||
|
*/
|
||||||
|
public function setRichTextElements($pElements = null)
|
||||||
|
{
|
||||||
|
if (is_array($pElements)) {
|
||||||
|
$this->_richTextElements = $pElements;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Invalid PHPExcel_RichText_ITextElement[] array passed.");
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode() {
|
||||||
|
$hashElements = '';
|
||||||
|
foreach ($this->_richTextElements as $element) {
|
||||||
|
$hashElements .= $element->getHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return md5(
|
||||||
|
$hashElements
|
||||||
|
. __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,64 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* 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_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_RichText_ITextElement
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
interface PHPExcel_RichText_ITextElement
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get text
|
||||||
|
*
|
||||||
|
* @return string Text
|
||||||
|
*/
|
||||||
|
public function getText();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text
|
||||||
|
*
|
||||||
|
* @param $pText string Text
|
||||||
|
* @return PHPExcel_RichText_ITextElement
|
||||||
|
*/
|
||||||
|
public function setText($pText = '');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get font
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style_Font
|
||||||
|
*/
|
||||||
|
public function getFont();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode();
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* 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_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_RichText_Run
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Font
|
||||||
|
*
|
||||||
|
* @var PHPExcel_Style_Font
|
||||||
|
*/
|
||||||
|
private $_font;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_RichText_Run instance
|
||||||
|
*
|
||||||
|
* @param string $pText Text
|
||||||
|
*/
|
||||||
|
public function __construct($pText = '')
|
||||||
|
{
|
||||||
|
// Initialise variables
|
||||||
|
$this->setText($pText);
|
||||||
|
$this->_font = new PHPExcel_Style_Font();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get font
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style_Font
|
||||||
|
*/
|
||||||
|
public function getFont() {
|
||||||
|
return $this->_font;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set font
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Style_Font $pFont Font
|
||||||
|
* @throws Exception
|
||||||
|
* @return PHPExcel_RichText_ITextElement
|
||||||
|
*/
|
||||||
|
public function setFont(PHPExcel_Style_Font $pFont = null) {
|
||||||
|
$this->_font = $pFont;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode() {
|
||||||
|
return md5(
|
||||||
|
$this->getText()
|
||||||
|
. $this->_font->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,108 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* 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_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_RichText_TextElement
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_RichText
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Text
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $_text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PHPExcel_RichText_TextElement instance
|
||||||
|
*
|
||||||
|
* @param string $pText Text
|
||||||
|
*/
|
||||||
|
public function __construct($pText = '')
|
||||||
|
{
|
||||||
|
// Initialise variables
|
||||||
|
$this->_text = $pText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get text
|
||||||
|
*
|
||||||
|
* @return string Text
|
||||||
|
*/
|
||||||
|
public function getText() {
|
||||||
|
return $this->_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text
|
||||||
|
*
|
||||||
|
* @param $pText string Text
|
||||||
|
* @return PHPExcel_RichText_ITextElement
|
||||||
|
*/
|
||||||
|
public function setText($pText = '') {
|
||||||
|
$this->_text = $pText;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get font
|
||||||
|
*
|
||||||
|
* @return PHPExcel_Style_Font
|
||||||
|
*/
|
||||||
|
public function getFont() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash code
|
||||||
|
*
|
||||||
|
* @return string Hash code
|
||||||
|
*/
|
||||||
|
public function getHashCode() {
|
||||||
|
return md5(
|
||||||
|
$this->_text
|
||||||
|
. __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,65 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Settings
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** PHPExcel root directory */
|
||||||
|
if (!defined('PHPEXCEL_ROOT')) {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../');
|
||||||
|
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
|
||||||
|
PHPExcel_Autoloader::Register();
|
||||||
|
PHPExcel_Shared_ZipStreamWrapper::register();
|
||||||
|
// check mbstring.func_overload
|
||||||
|
if (ini_get('mbstring.func_overload') & 2) {
|
||||||
|
throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PHPExcel_Settings
|
||||||
|
{
|
||||||
|
public static function getCacheStorageMethod() {
|
||||||
|
return PHPExcel_CachedObjectStorageFactory::$_cacheStorageMethod;
|
||||||
|
} // function getCacheStorageMethod()
|
||||||
|
|
||||||
|
|
||||||
|
public static function getCacheStorageClass() {
|
||||||
|
return PHPExcel_CachedObjectStorageFactory::$_cacheStorageClass;
|
||||||
|
} // function getCacheStorageClass()
|
||||||
|
|
||||||
|
|
||||||
|
public static function setCacheStorageMethod($method = PHPExcel_CachedObjectStorageFactory::cache_in_memory, $arguments = array()) {
|
||||||
|
return PHPExcel_CachedObjectStorageFactory::initialize($method,$arguments);
|
||||||
|
} // function setCacheStorageMethod()
|
||||||
|
|
||||||
|
|
||||||
|
public static function setLocale($locale){
|
||||||
|
return PHPExcel_Calculation::getInstance()->setLocale($locale);
|
||||||
|
} // function setLocale()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_CodePage
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Shared_CodePage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Convert Microsoft Code Page Identifier to Code Page Name which iconv
|
||||||
|
* and mbstring understands
|
||||||
|
*
|
||||||
|
* @param int $number Microsoft Code Page Indentifier
|
||||||
|
* @return string Code Page Name
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function NumberToName($codePage = '1252')
|
||||||
|
{
|
||||||
|
switch ($codePage) {
|
||||||
|
case 367: return 'ASCII'; break; // ASCII
|
||||||
|
case 437: return 'CP437'; break; //OEM US
|
||||||
|
case 720: throw new Exception('Code page 720 not supported.');
|
||||||
|
break; //OEM Arabic
|
||||||
|
case 737: return 'CP737'; break; //OEM Greek
|
||||||
|
case 775: return 'CP775'; break; //OEM Baltic
|
||||||
|
case 850: return 'CP850'; break; //OEM Latin I
|
||||||
|
case 852: return 'CP852'; break; //OEM Latin II (Central European)
|
||||||
|
case 855: return 'CP855'; break; //OEM Cyrillic
|
||||||
|
case 857: return 'CP857'; break; //OEM Turkish
|
||||||
|
case 858: return 'CP858'; break; //OEM Multilingual Latin I with Euro
|
||||||
|
case 860: return 'CP860'; break; //OEM Portugese
|
||||||
|
case 861: return 'CP861'; break; //OEM Icelandic
|
||||||
|
case 862: return 'CP862'; break; //OEM Hebrew
|
||||||
|
case 863: return 'CP863'; break; //OEM Canadian (French)
|
||||||
|
case 864: return 'CP864'; break; //OEM Arabic
|
||||||
|
case 865: return 'CP865'; break; //OEM Nordic
|
||||||
|
case 866: return 'CP866'; break; //OEM Cyrillic (Russian)
|
||||||
|
case 869: return 'CP869'; break; //OEM Greek (Modern)
|
||||||
|
case 874: return 'CP874'; break; //ANSI Thai
|
||||||
|
case 932: return 'CP932'; break; //ANSI Japanese Shift-JIS
|
||||||
|
case 936: return 'CP936'; break; //ANSI Chinese Simplified GBK
|
||||||
|
case 949: return 'CP949'; break; //ANSI Korean (Wansung)
|
||||||
|
case 950: return 'CP950'; break; //ANSI Chinese Traditional BIG5
|
||||||
|
case 1200: return 'UTF-16LE'; break; //UTF-16 (BIFF8)
|
||||||
|
case 1250: return 'CP1250'; break; // ANSI Latin II (Central European)
|
||||||
|
case 1251: return 'CP1251'; break; //ANSI Cyrillic
|
||||||
|
case 1252: return 'CP1252'; break; //ANSI Latin I (BIFF4-BIFF7)
|
||||||
|
case 1253: return 'CP1253'; break; //ANSI Greek
|
||||||
|
case 1254: return 'CP1254'; break; //ANSI Turkish
|
||||||
|
case 1255: return 'CP1255'; break; //ANSI Hebrew
|
||||||
|
case 1256: return 'CP1256'; break; //ANSI Arabic
|
||||||
|
case 1257: return 'CP1257'; break; //ANSI Baltic
|
||||||
|
case 1258: return 'CP1258'; break; //ANSI Vietnamese
|
||||||
|
case 1361: return 'CP1361'; break; //ANSI Korean (Johab)
|
||||||
|
case 10000: return 'MAC'; break; //Apple Roman
|
||||||
|
case 32768: return 'MAC'; break; //Apple Roman
|
||||||
|
case 32769: throw new Exception('Code page 32769 not supported.');
|
||||||
|
break; //ANSI Latin I (BIFF2-BIFF3)
|
||||||
|
case 65001: return 'UTF-8'; break; //Unicode (UTF-8)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('Unknown codepage: ' . $codePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,303 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Date
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
|
||||||
|
private static $ExcelBaseDate = self::CALENDAR_WINDOWS_1900;
|
||||||
|
|
||||||
|
public static $dateTimeObjectType = 'DateTime';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the Excel calendar (Windows 1900 or Mac 1904)
|
||||||
|
*
|
||||||
|
* @param integer $baseDate Excel base date
|
||||||
|
* @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;
|
||||||
|
} // function setExcelCalendar()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Excel calendar (Windows 1900 or Mac 1904)
|
||||||
|
*
|
||||||
|
* @return integer $baseDate Excel base date
|
||||||
|
*/
|
||||||
|
public static function getExcelCalendar() {
|
||||||
|
return self::$ExcelBaseDate;
|
||||||
|
} // function getExcelCalendar()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a date from Excel to PHP
|
||||||
|
*
|
||||||
|
* @param long $dateValue Excel date/time value
|
||||||
|
* @return long PHP serialized date/time
|
||||||
|
*/
|
||||||
|
public static function ExcelToPHP($dateValue = 0) {
|
||||||
|
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 * 24 * 60 * 60);
|
||||||
|
if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) {
|
||||||
|
$returnValue = (integer) $returnValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$hours = round($dateValue * 24);
|
||||||
|
$mins = round($dateValue * 24 * 60) - round($hours * 60);
|
||||||
|
$secs = round($dateValue * 24 * 60 * 60) - round($hours * 60 * 60) - round($mins * 60);
|
||||||
|
$returnValue = (integer) gmmktime($hours, $mins, $secs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return $returnValue;
|
||||||
|
} // function ExcelToPHP()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a date from Excel to a PHP Date/Time object
|
||||||
|
*
|
||||||
|
* @param long $dateValue Excel date/time value
|
||||||
|
* @return long 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;
|
||||||
|
} // function ExcelToPHPObject()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a date from PHP to Excel
|
||||||
|
*
|
||||||
|
* @param mixed $dateValue PHP serialized date/time or date object
|
||||||
|
* @return mixed Excel date/time value
|
||||||
|
* or boolean False on failure
|
||||||
|
*/
|
||||||
|
public static function PHPToExcel($dateValue = 0) {
|
||||||
|
$saveTimeZone = date_default_timezone_get();
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
$retValue = False;
|
||||||
|
if ((is_object($dateValue)) && ($dateValue instanceof self::$dateTimeObjectType)) {
|
||||||
|
$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)) {
|
||||||
|
$retValue = self::FormattedPHPToExcel( date('Y',$dateValue), date('m',$dateValue), date('d',$dateValue),
|
||||||
|
date('H',$dateValue), date('i',$dateValue), date('s',$dateValue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
date_default_timezone_set($saveTimeZone);
|
||||||
|
|
||||||
|
return $retValue;
|
||||||
|
} // function PHPToExcel()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FormattedPHPToExcel
|
||||||
|
*
|
||||||
|
* @param long $year
|
||||||
|
* @param long $month
|
||||||
|
* @param long $day
|
||||||
|
* @param long $hours
|
||||||
|
* @param long $minutes
|
||||||
|
* @param long $seconds
|
||||||
|
* @return long 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 = $month - 3;
|
||||||
|
} else {
|
||||||
|
$month = $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;
|
||||||
|
} // function FormattedPHPToExcel()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a given cell a date/time?
|
||||||
|
*
|
||||||
|
* @param PHPExcel_Cell $pCell
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function isDateTime(PHPExcel_Cell $pCell) {
|
||||||
|
return self::isDateTimeFormat($pCell->getParent()->getStyle($pCell->getCoordinate())->getNumberFormat());
|
||||||
|
} // function isDateTime()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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());
|
||||||
|
} // function isDateTimeFormat()
|
||||||
|
|
||||||
|
|
||||||
|
private static $possibleDateFormatCharacters = 'ymdHis';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a given number format code a date/time?
|
||||||
|
*
|
||||||
|
* @param string $pFormatCode
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function isDateTimeFormatCode($pFormatCode = '') {
|
||||||
|
// Switch on formatcode
|
||||||
|
switch ($pFormatCode) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try checking for any of the date formatting characters that don't appear within square braces
|
||||||
|
if (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$pFormatCode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No date...
|
||||||
|
return false;
|
||||||
|
} // function isDateTimeFormatCode()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = '') {
|
||||||
|
// restrict to dates and times like these because date_parse accepts too many strings
|
||||||
|
// '2009-12-31'
|
||||||
|
// '2009-12-31 15:59'
|
||||||
|
// '2009-12-31 15:59:10'
|
||||||
|
if (!preg_match('/^\d{4}\-\d{1,2}\-\d{1,2}( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/', $dateValue)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now try with date_parse
|
||||||
|
$PHPDateArray = date_parse($dateValue);
|
||||||
|
|
||||||
|
if ($PHPDateArray['error_count'] == 0) {
|
||||||
|
$year = $PHPDateArray['year'] !== false ? $PHPDateArray['year'] : self::getExcelCalendar();
|
||||||
|
$month = $PHPDateArray['month'] !== false ? $PHPDateArray['month'] : 1;
|
||||||
|
$day = $PHPDateArray['day'] !== false ? $PHPDateArray['day'] : 0;
|
||||||
|
$hour = $PHPDateArray['hour'] !== false ? $PHPDateArray['hour'] : 0;
|
||||||
|
$minute = $PHPDateArray['minute'] !== false ? $PHPDateArray['minute'] : 0;
|
||||||
|
$second = $PHPDateArray['second'] !== false ? $PHPDateArray['second'] : 0;
|
||||||
|
|
||||||
|
$excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year, $month, $day, $hour, $minute, $second);
|
||||||
|
|
||||||
|
return $excelDateValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Drawing
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 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,91 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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,83 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher_DgContainer
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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,109 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher_DgContainer_SpgrContainer
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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,368 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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 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 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,203 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher_DggContainer
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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,65 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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,120 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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,91 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared_Escher
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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,317 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Excel5
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
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 integer $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);
|
||||||
|
|
||||||
|
} else if ($sheet->getDefaultColumnDimension()->getWidth() != -1) {
|
||||||
|
|
||||||
|
// then we have default column dimension with explicit width
|
||||||
|
$defaultColumnDimension = $sheet->getDefaultColumnDimension();
|
||||||
|
$width = $defaultColumnDimension->getWidth();
|
||||||
|
$pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $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
|
||||||
|
|
||||||
|
} else if ($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 $startOffset Offset within start cell measured in 1/1024 of the cell width
|
||||||
|
* @param string $endColumn
|
||||||
|
* @param integer $endOffset 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 string $startRow (1-based)
|
||||||
|
* @param integer $startOffset Offset within start cell measured in 1/256 of the cell height
|
||||||
|
* @param string $endRow (1-based)
|
||||||
|
* @param integer $endOffset 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,139 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_File
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Shared_File
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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 == '' || is_null($returnValue)) {
|
||||||
|
$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()
|
||||||
|
{
|
||||||
|
// 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 (file_exists($temp)) { return realpath($temp); }
|
||||||
|
}
|
||||||
|
if ($temp = getenv('TEMP') ) {
|
||||||
|
if (file_exists($temp)) { return realpath($temp); }
|
||||||
|
}
|
||||||
|
if ($temp = getenv('TMPDIR') ) {
|
||||||
|
if (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,763 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPExcel
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 - 2010 PHPExcel
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
|
||||||
|
* @version ##VERSION##, ##DATE##
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPExcel_Shared_Font
|
||||||
|
*
|
||||||
|
* @category PHPExcel
|
||||||
|
* @package PHPExcel_Shared
|
||||||
|
* @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
|
||||||
|
*/
|
||||||
|
class PHPExcel_Shared_Font
|
||||||
|
{
|
||||||
|
/* Methods for resolving autosize value */
|
||||||
|
const AUTOSIZE_METHOD_APPROX = 'approx';
|
||||||
|
const AUTOSIZE_METHOD_EXACT = 'exact';
|
||||||
|
|
||||||
|
/** Character set codes used by BIFF5-8 in Font records */
|
||||||
|
const CHARSET_ANSI_LATIN = 0x00;
|
||||||
|
const CHARSET_SYSTEM_DEFAULT = 0x01;
|
||||||
|
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;
|
||||||
|
const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88;
|
||||||
|
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 = 0xDE;
|
||||||
|
const CHARSET_ANSI_LATIN_II = 0xEE;
|
||||||
|
const CHARSET_OEM_LATIN_I = 0xFF;
|
||||||
|
|
||||||
|
// XXX: Constants created!
|
||||||
|
/** Font filenames */
|
||||||
|
const ARIAL = 'arial.ttf';
|
||||||
|
const ARIAL_BOLD = 'arialbd.ttf';
|
||||||
|
const ARIAL_ITALIC = 'ariali.ttf';
|
||||||
|
const ARIAL_BOLD_ITALIC = 'arialbi.ttf';
|
||||||
|
|
||||||
|
const CALIBRI = 'CALIBRI.TTF';
|
||||||
|
const CALIBRI_BOLD = 'CALIBRIB.TTF';
|
||||||
|
const CALIBRI_ITALIC = 'CALIBRII.TTF';
|
||||||
|
const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF';
|
||||||
|
|
||||||
|
const COMIC_SANS_MS = 'comic.ttf';
|
||||||
|
const COMIC_SANS_MS_BOLD = 'comicbd.ttf';
|
||||||
|
|
||||||
|
const COURIER_NEW = 'cour.ttf';
|
||||||
|
const COURIER_NEW_BOLD = 'courbd.ttf';
|
||||||
|
const COURIER_NEW_ITALIC = 'couri.ttf';
|
||||||
|
const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf';
|
||||||
|
|
||||||
|
const GEORGIA = 'georgia.ttf';
|
||||||
|
const GEORGIA_BOLD = 'georgiab.ttf';
|
||||||
|
const GEORGIA_ITALIC = 'georgiai.ttf';
|
||||||
|
const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf';
|
||||||
|
|
||||||
|
const IMPACT = 'impact.ttf';
|
||||||
|
|
||||||
|
const LIBERATION_SANS = 'LiberationSans-Regular.ttf';
|
||||||
|
const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf';
|
||||||
|
const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf';
|
||||||
|
const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf';
|
||||||
|
|
||||||
|
const LUCIDA_CONSOLE = 'lucon.ttf';
|
||||||
|
const LUCIDA_SANS_UNICODE = 'l_10646.ttf';
|
||||||
|
|
||||||
|
const MICROSOFT_SANS_SERIF = 'micross.ttf';
|
||||||
|
|
||||||
|
const PALATINO_LINOTYPE = 'pala.ttf';
|
||||||
|
const PALATINO_LINOTYPE_BOLD = 'palab.ttf';
|
||||||
|
const PALATINO_LINOTYPE_ITALIC = 'palai.ttf';
|
||||||
|
const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf';
|
||||||
|
|
||||||
|
const SYMBOL = 'symbol.ttf';
|
||||||
|
|
||||||
|
const TAHOMA = 'tahoma.ttf';
|
||||||
|
const TAHOMA_BOLD = 'tahomabd.ttf';
|
||||||
|
|
||||||
|
const TIMES_NEW_ROMAN = 'times.ttf';
|
||||||
|
const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf';
|
||||||
|
const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf';
|
||||||
|
const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf';
|
||||||
|
|
||||||
|
const TREBUCHET_MS = 'trebuc.ttf';
|
||||||
|
const TREBUCHET_MS_BOLD = 'trebucbd.ttf';
|
||||||
|
const TREBUCHET_MS_ITALIC = 'trebucit.ttf';
|
||||||
|
const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf';
|
||||||
|
|
||||||
|
const VERDANA = 'verdana.ttf';
|
||||||
|
const VERDANA_BOLD = 'verdanab.ttf';
|
||||||
|
const VERDANA_ITALIC = 'verdanai.ttf';
|
||||||
|
const VERDANA_BOLD_ITALIC = 'verdanaz.ttf';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AutoSize method
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to folder containing TrueType font .ttf files
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $trueTypeFontPath = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How wide is a default column for a given default font and size?
|
||||||
|
* Empirical data found by inspecting real Excel files and reading off the pixel width
|
||||||
|
* in Microsoft Office Excel 2007.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public static $defaultColumnWidths = array(
|
||||||
|
'Arial' => array(
|
||||||
|
1 => array('px' => 24, 'width' => 12.00000000),
|
||||||
|
2 => array('px' => 24, 'width' => 12.00000000),
|
||||||
|
3 => array('px' => 32, 'width' => 10.66406250),
|
||||||
|
4 => array('px' => 32, 'width' => 10.66406250),
|
||||||
|
5 => array('px' => 40, 'width' => 10.00000000),
|
||||||
|
6 => array('px' => 48, 'width' => 9.59765625),
|
||||||
|
7 => array('px' => 48, 'width' => 9.59765625),
|
||||||
|
8 => array('px' => 56, 'width' => 9.33203125),
|
||||||
|
9 => array('px' => 64, 'width' => 9.14062500),
|
||||||
|
10 => array('px' => 64, 'width' => 9.14062500),
|
||||||
|
),
|
||||||
|
'Calibri' => array(
|
||||||
|
1 => array('px' => 24, 'width' => 12.00000000),
|
||||||
|
2 => array('px' => 24, 'width' => 12.00000000),
|
||||||
|
3 => array('px' => 32, 'width' => 10.66406250),
|
||||||
|
4 => array('px' => 32, 'width' => 10.66406250),
|
||||||
|
5 => array('px' => 40, 'width' => 10.00000000),
|
||||||
|
6 => array('px' => 48, 'width' => 9.59765625),
|
||||||
|
7 => array('px' => 48, 'width' => 9.59765625),
|
||||||
|
8 => array('px' => 56, 'width' => 9.33203125),
|
||||||
|
9 => array('px' => 56, 'width' => 9.33203125),
|
||||||
|
10 => array('px' => 64, 'width' => 9.14062500),
|
||||||
|
11 => array('px' => 64, 'width' => 9.14062500),
|
||||||
|
),
|
||||||
|
'Verdana' => array(
|
||||||
|
1 => array('px' => 24, 'width' => 12.00000000),
|
||||||
|
2 => array('px' => 24, 'width' => 12.00000000),
|
||||||
|
3 => array('px' => 32, 'width' => 10.66406250),
|
||||||
|
4 => array('px' => 32, 'width' => 10.66406250),
|
||||||
|
5 => array('px' => 40, 'width' => 10.00000000),
|
||||||
|
6 => array('px' => 48, 'width' => 9.59765625),
|
||||||
|
7 => array('px' => 48, 'width' => 9.59765625),
|
||||||
|
8 => array('px' => 64, 'width' => 9.14062500),
|
||||||
|
9 => array('px' => 72, 'width' => 9.00000000),
|
||||||
|
10 => array('px' => 72, 'width' => 9.00000000),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set autoSize method
|
||||||
|
*
|
||||||
|
* @param string $pValue
|
||||||
|
*/
|
||||||
|
public static function setAutoSizeMethod($pValue = 'approx')
|
||||||
|
{
|
||||||
|
self::$autoSizeMethod = $pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get autoSize method
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getAutoSizeMethod()
|
||||||
|
{
|
||||||
|
return self::$autoSizeMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the path to the folder containing .ttf files. There should be a trailing slash.
|
||||||
|
* Typical locations on variout some platforms:
|
||||||
|
* <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 int $fontSize Font size (in pixels or points)
|
||||||
|
* @param bool $fontSizeInPixels Is the font size specified in pixels (true) or in points (false) ?
|
||||||
|
* @param string $cellText Text to calculate width
|
||||||
|
* @param int $rotation Rotation angle
|
||||||
|
* @return int 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);
|
||||||
|
$lineWitdhs = 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
|
||||||
|
try {
|
||||||
|
// If autosize method is set to 'approx', use approximation
|
||||||
|
if (self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX) {
|
||||||
|
throw new Exception('AutoSize method is set to approx');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width of text in pixels excl. padding
|
||||||
|
$columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation);
|
||||||
|
|
||||||
|
// Excel adds some padding, use 1.07 of the width of an 'n' glyph
|
||||||
|
$columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07); // pixels incl. padding
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Width of text in pixels excl. padding, approximation
|
||||||
|
$columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation);
|
||||||
|
|
||||||
|
// Excel adds some padding, just use approx width of 'n' glyph
|
||||||
|
$columnWidth += self::getTextWidthPixelsApprox('n', $font, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from pixel width to column width
|
||||||
|
$columnWidth = PHPExcel_Shared_Drawing::pixelsToCellDimension($columnWidth, $defaultFont);
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return round($columnWidth, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get GD text width in pixels for a string of text in a certain font at a certain rotation angle
|
||||||
|
*
|
||||||
|
* @param string $text
|
||||||
|
* @param PHPExcel_Style_Font
|
||||||
|
* @param int $rotation
|
||||||
|
* @return int
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) {
|
||||||
|
if (!function_exists('imagettfbbox')) {
|
||||||
|
throw new Exception('GD library needs to be enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// font size should really be supplied in pixels in GD2,
|
||||||
|
// but since GD2 seems to assume 72dpi, pixels and points are the same
|
||||||
|
$fontFile = self::getTrueTypeFontFileFromFont($font);
|
||||||
|
$textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text);
|
||||||
|
|
||||||
|
// Get corners positions
|
||||||
|
$lowerLeftCornerX = $textBox[0];
|
||||||
|
$lowerLeftCornerY = $textBox[1];
|
||||||
|
$lowerRightCornerX = $textBox[2];
|
||||||
|
$lowerRightCornerY = $textBox[3];
|
||||||
|
$upperRightCornerX = $textBox[4];
|
||||||
|
$upperRightCornerY = $textBox[5];
|
||||||
|
$upperLeftCornerX = $textBox[6];
|
||||||
|
$upperLeftCornerY = $textBox[7];
|
||||||
|
|
||||||
|
// Consider the rotation when calculating the width
|
||||||
|
$textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX);
|
||||||
|
|
||||||
|
return $textWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get approximate width in pixels for a string of text in a certain font at a certain rotation angle
|
||||||
|
*
|
||||||
|
* @param string $columnText
|
||||||
|
* @param PHPExcel_Style_Font $font
|
||||||
|
* @param int $rotation
|
||||||
|
* @return int Text width in pixels (no padding added)
|
||||||
|
*/
|
||||||
|
public static function getTextWidthPixelsApprox($columnText, PHPExcel_Style_Font $font = null, $rotation = 0)
|
||||||
|
{
|
||||||
|
$fontName = $font->getName();
|
||||||
|
$fontSize = $font->getSize();
|
||||||
|
|
||||||
|
// Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size.
|
||||||
|
switch ($fontName) {
|
||||||
|
case 'Calibri':
|
||||||
|
// value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font.
|
||||||
|
$columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText));
|
||||||
|
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Arial':
|
||||||
|
// value 7 was found via interpolation by inspecting real Excel files with Arial 10 font.
|
||||||
|
$columnWidth = (int) (7 * PHPExcel_Shared_String::CountCharacters($columnText));
|
||||||
|
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Verdana':
|
||||||
|
// value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font.
|
||||||
|
$columnWidth = (int) (8 * PHPExcel_Shared_String::CountCharacters($columnText));
|
||||||
|
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// just assume Calibri
|
||||||
|
$columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText));
|
||||||
|
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate approximate rotated column width
|
||||||
|
if ($rotation !== 0) {
|
||||||
|
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
|
||||||
|
$columnWidth = (int) $columnWidth;
|
||||||
|
return $columnWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate an (approximate) pixel size, based on a font points size
|
||||||
|
*
|
||||||
|
* @param int $fontSizeInPoints Font size (in points)
|
||||||
|
* @return int Font size (in pixels)
|
||||||
|
*/
|
||||||
|
public static function fontSizeToPixels($fontSizeInPoints = 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 Exception('Valid directory to TrueType Font files not specified');
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $font->getName();
|
||||||
|
$bold = $font->getBold();
|
||||||
|
$italic = $font->getItalic();
|
||||||
|
|
||||||
|
// Check if we can map font to true type font file
|
||||||
|
switch ($name) {
|
||||||
|
case 'Arial':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD)
|
||||||
|
: ($italic ? self::ARIAL_ITALIC : self::ARIAL)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Calibri':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD)
|
||||||
|
: ($italic ? self::CALIBRI_ITALIC : self::CALIBRI)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Courier New':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD)
|
||||||
|
: ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Comic Sans MS':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Georgia':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD)
|
||||||
|
: ($italic ? self::GEORGIA_ITALIC : self::GEORGIA)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Impact':
|
||||||
|
$fontFile = self::IMPACT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Liberation Sans':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD)
|
||||||
|
: ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Lucida Console':
|
||||||
|
$fontFile = self::LUCIDA_CONSOLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Lucida Sans Unicode':
|
||||||
|
$fontFile = self::LUCIDA_SANS_UNICODE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Microsoft Sans Serif':
|
||||||
|
$fontFile = self::MICROSOFT_SANS_SERIF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Palatino Linotype':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD)
|
||||||
|
: ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Symbol':
|
||||||
|
$fontFile = self::SYMBOL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Tahoma':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? self::TAHOMA_BOLD : self::TAHOMA
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Times New Roman':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD)
|
||||||
|
: ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Trebuchet MS':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD)
|
||||||
|
: ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Verdana':
|
||||||
|
$fontFile = (
|
||||||
|
$bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD)
|
||||||
|
: ($italic ? self::VERDANA_ITALIC : self::VERDANA)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fontFile = self::$trueTypeFontPath . $fontFile;
|
||||||
|
|
||||||
|
// Check if file actually exists
|
||||||
|
if (!file_exists($fontFile)) {
|
||||||
|
throw New Exception('TrueType Font file not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $fontFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the associated charset for the font name.
|
||||||
|
*
|
||||||
|
* @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,149 @@
|
||||||
|
<?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 Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
|
} // 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 Exception(JAMAError(MatrixSPDException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixDimensionException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
|
} // function solve()
|
||||||
|
|
||||||
|
} // class CholeskyDecomposition
|
|
@ -0,0 +1,862 @@
|
||||||
|
<?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
|
||||||
|
} else if ($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
|
||||||
|
} else if ($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);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // class EigenvalueDecomposition
|
|
@ -0,0 +1,255 @@
|
||||||
|
<?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 LUDecomposition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 Matrix) {
|
||||||
|
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
|
||||||
|
$this->LU = $A->getArrayCopy();
|
||||||
|
$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 Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
|
} // 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 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 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 Exception(JAMAError(MatrixDimensionException));
|
||||||
|
}
|
||||||
|
} // 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,:)
|
||||||
|
* @exception IllegalArgumentException Matrix row dimensions must agree.
|
||||||
|
* @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 Exception(JAMAError(MatrixSingularException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixSquareException));
|
||||||
|
}
|
||||||
|
} // function solve()
|
||||||
|
|
||||||
|
} // class LUDecomposition
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,232 @@
|
||||||
|
<?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 QRDecomposition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 Exception(JAMAError(ArgumentTypeException));
|
||||||
|
}
|
||||||
|
} // 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 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 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 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 Matrix($X);
|
||||||
|
return ($X->getMatrix(0, $this->n-1, 0, $nx));
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixRankException));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception(JAMAError(MatrixDimensionException));
|
||||||
|
}
|
||||||
|
} // function solve()
|
||||||
|
|
||||||
|
} // class QRDecomposition
|
|
@ -0,0 +1,526 @@
|
||||||
|
<?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;
|
||||||
|
} else if ($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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // class SingularValueDecomposition
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
require_once "includes/header.php";
|
||||||
|
require_once "includes/navbar.php";
|
||||||
|
require_once "sections/Home.php";
|
||||||
|
require_once "includes/footer.php";
|
||||||
|
?>
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Script to create REGRESS package for download
|
||||||
|
*
|
||||||
|
* @author Mike Bommarito
|
||||||
|
* @author Paul Meagher
|
||||||
|
* @version 0.3
|
||||||
|
* @modified Apr 2, 2006
|
||||||
|
*
|
||||||
|
* Note: Script requires the PEAR Archive_Tar package be installed:
|
||||||
|
*
|
||||||
|
* @see http://pear.php.net/package/Archive_Tar
|
||||||
|
*/
|
||||||
|
|
||||||
|
// name and directory of package
|
||||||
|
$pkgName = "JAMA";
|
||||||
|
|
||||||
|
// root of PHP/Math build directory
|
||||||
|
$buildDir = substr(dirname(__FILE__), 0, -5 - strlen($pkgName));
|
||||||
|
|
||||||
|
// switch to PHP/Math build directory
|
||||||
|
chdir($buildDir);
|
||||||
|
|
||||||
|
$tarName = "$pkgName.tar.gz";
|
||||||
|
|
||||||
|
$tarPath = $buildDir.$pkgName."/downloads/".$tarName;
|
||||||
|
|
||||||
|
if($_GET['op'] == "download") {
|
||||||
|
|
||||||
|
require_once('Archive/Tar.php');
|
||||||
|
|
||||||
|
$tar = new Archive_Tar($tarPath);
|
||||||
|
|
||||||
|
// create $pkgName archive under $pkgName folder
|
||||||
|
$files = glob("$pkgName/*.php");
|
||||||
|
$files = array_merge($files, glob("$pkgName/*.TXT"));
|
||||||
|
$files = array_merge($files, glob("$pkgName/docs/*.php"));
|
||||||
|
$files = array_merge($files, glob("$pkgName/docs/includes/*.php"));
|
||||||
|
$files = array_merge($files, glob("$pkgName/examples/*.php"));
|
||||||
|
$files = array_merge($files, glob("$pkgName/tests/*.php"));
|
||||||
|
$files = array_merge($files, glob("$pkgName/utils/*.php"));
|
||||||
|
|
||||||
|
$tar->create($files);
|
||||||
|
|
||||||
|
// create the download url
|
||||||
|
$webDir = substr($_SERVER['PHP_SELF'], 0, -18);
|
||||||
|
$urlPath = "http://".$_SERVER['HTTP_HOST'].$webDir."/downloads";
|
||||||
|
|
||||||
|
// redirect to download url
|
||||||
|
header("Location: $urlPath/$tarName");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
include_once "includes/header.php";
|
||||||
|
include_once "includes/navbar.php";
|
||||||
|
?>
|
||||||
|
<p>
|
||||||
|
Download current version:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href='<?php echo $_SERVER['PHP_SELF']."?op=download"; ?>'><?php echo $tarName ?></a></li>
|
||||||
|
</ul>
|
||||||
|
<?php
|
||||||
|
include_once "includes/footer.php";
|
||||||
|
?>
|
|
@ -0,0 +1,166 @@
|
||||||
|
<?php
|
||||||
|
include_once "includes/header.php";
|
||||||
|
include_once "includes/navbar.php";
|
||||||
|
?>
|
||||||
|
<h2>Magic Square Example</h2>
|
||||||
|
<p>
|
||||||
|
The Jama distribution comes with a magic square example that is used to
|
||||||
|
test and benchmark the LU, QR, SVD and symmetric Eig decompositions.
|
||||||
|
The example outputs a multi-column table with these column headings:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table border='1' cellpadding='5' cellspacing='0' align='center'>
|
||||||
|
<tr>
|
||||||
|
<td><b>n</b></td>
|
||||||
|
<td>Order of magic square.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>trace</b></td>
|
||||||
|
<td>Diagonal sum, should be the magic sum, (n^3 + n)/2.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>max_eig</b></td>
|
||||||
|
<td>Maximum eigenvalue of (A + A')/2, should equal trace.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>rank</b></td>
|
||||||
|
<td>Linear algebraic rank, should equal n if n is odd, be less than n if n is even.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>cond</b></td>
|
||||||
|
<td>L_2 condition number, ratio of singular values.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>lu_res</b></td>
|
||||||
|
<td>test of LU factorization, norm1(L*U-A(p,:))/(n*eps).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>qr_res</b></td>
|
||||||
|
<td>test of QR factorization, norm1(Q*R-A)/(n*eps).</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p>
|
||||||
|
Running the Java-based version of the matix square example produces these results:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table border='1' align='center'>
|
||||||
|
<tr>
|
||||||
|
<th> n </th>
|
||||||
|
<th> trace </th>
|
||||||
|
<th> max_eig </th>
|
||||||
|
<th> rank </th>
|
||||||
|
<th> cond </th>
|
||||||
|
<th> lu_res </th>
|
||||||
|
<th> qr_res </th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>3</td><td>15</td><td>15.000</td><td>3</td><td>4.330</td><td>0.000</td><td>11.333</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>4</td><td>34</td><td>34.000</td><td>3</td><td> Inf</td><td>0.000</td><td>13.500</td>
|
||||||
|
<tr>
|
||||||
|
<td>5</td><td>65</td><td>65.000</td><td>5</td><td>5.462</td><td>0.000</td><td>14.400</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>6</td><td>111</td><td>111.000</td><td>5</td><td> Inf</td><td>5.333</td><td>16.000</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>7</td><td>175</td><td>175.000</td><td>7</td><td>7.111</td><td>2.286</td><td>37.714</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>8</td><td>260</td><td>260.000</td><td>3</td><td> Inf</td><td>0.000</td><td>59.000</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>9</td><td>369</td><td>369.000</td><td>9</td><td>9.102</td><td>7.111</td><td>53.333</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>10</td><td>505</td><td>505.000</td><td>7</td><td> Inf</td><td>3.200</td><td>159.200</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>11</td><td>671</td><td>671.000</td><td>11</td><td>11.102</td><td>2.909</td><td>215.273</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>12</td><td>870</td><td>870.000</td><td>3</td><td> Inf</td><td>0.000</td><td>185.333</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>13</td><td>1105</td><td>1105.000</td><td>13</td><td>13.060</td><td>4.923</td><td>313.846</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>14</td><td>1379</td><td>1379.000</td><td>9</td><td> Inf</td><td>4.571</td><td>540.571</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>15</td><td>1695</td><td>1695.000</td><td>15</td><td>15.062</td><td>4.267</td><td>242.133</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>16</td><td>2056</td><td>2056.000</td><td>3</td><td> Inf</td><td>0.000</td><td>488.500</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>17</td><td>2465</td><td>2465.000</td><td>17</td><td>17.042</td><td>7.529</td><td>267.294</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>18</td><td>2925</td><td>2925.000</td><td>11</td><td> Inf</td><td>7.111</td><td>520.889</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>19</td><td>3439</td><td>3439.000</td><td>19</td><td>19.048</td><td>16.842</td><td>387.368</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>20</td><td>4010</td><td>4010.000</td><td>3</td><td> Inf</td><td>14.400</td><td>584.800</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>21</td><td>4641</td><td>4641.000</td><td>21</td><td>21.035</td><td>6.095</td><td>1158.095</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>22</td><td>5335</td><td>5335.000</td><td>13</td><td> Inf</td><td>6.545</td><td>1132.364</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>23</td><td>6095</td><td>6095.000</td><td>23</td><td>23.037</td><td>11.130</td><td>1268.870</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>24</td><td>6924</td><td>6924.000</td><td>3</td><td> Inf</td><td>10.667</td><td>827.500</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>25</td><td>7825</td><td>7825.000</td><td>25</td><td>25.029</td><td>35.840</td><td>1190.400</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>26</td><td>8801</td><td>8801.000</td><td>15</td><td> Inf</td><td>4.923</td><td>1859.077</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>27</td><td>9855</td><td>9855.000</td><td>27</td><td>27.032</td><td>37.926</td><td>1365.333</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>28</td><td>10990</td><td>10990.000</td><td>3</td><td> Inf</td><td>34.286</td><td>1365.714</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>29</td><td>12209</td><td>12209.000</td><td>29</td><td>29.025</td><td>30.897</td><td>1647.448</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>30</td><td>13515</td><td>13515.000</td><td>17</td><td> Inf</td><td>8.533</td><td>2571.733</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>31</td><td>14911</td><td>14911.000</td><td>31</td><td>31.027</td><td>33.032</td><td>1426.581</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>32</td><td>16400</td><td>16400.000</td><td>3</td><td> Inf</td><td>0.000</td><td>1600.125</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<center>Elapsed Time = 0.710 seconds</center>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The magic square example does not fare well when <a href='../examples/MagicSquareExample.php'>run as a PHP script</a>. For a 32x32 matrix array
|
||||||
|
it takes around a second to complete just the last row of computations in the above table.
|
||||||
|
Hopefully this result will spur PHP developers to find optimizations and better attuned algorithms
|
||||||
|
to speed things up. Matrix algebra is a great testing ground for ideas about time and memory
|
||||||
|
performance optimation. Keep in perspective that PHP JAMA scripts are still plenty fast for use as
|
||||||
|
a tool for learning about matrix algebra and quickly extending your knowledge with new scripts
|
||||||
|
to apply knowledge.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To learn more about the subject of magic squares you can visit the <a href='http://mathforum.org/alejandre/magic.square.html'>Drexel Math Forum on Magic Squares</a>.
|
||||||
|
You can also learn more by carefully examining the <code>MagicSquareExample.php</code> source code below.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
highlight_file("../examples/MagicSquareExample.php");
|
||||||
|
include_once "includes/footer.php";
|
||||||
|
?>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<div id="credits">
|
||||||
|
<p>
|
||||||
|
Brought to you by:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://math.nist.gov/">National Institute of Standards and Technology</a></li>
|
||||||
|
<li><a href="http://math.nist.gov/">MathWorks</a></li>
|
||||||
|
<li><a href="http://math.nist.gov/javanumerics/jama/">JAMA : A Java Matrix Package</a></li>
|
||||||
|
<li>Paul Meagher</li>
|
||||||
|
<li>Michael Bommarito</li>
|
||||||
|
<li>Lukasz Karapuda</li>
|
||||||
|
<li>Bartek Matosiuk</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
|
@ -0,0 +1,2 @@
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<title>JAMA v1.0.1</title>
|
||||||
|
<meta name="description" content="JAMA v1.0.1 - Port of the proposed standard Java Matrix Library to PHP" />
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta name="keywords" content="php, matrix, matrix library, cholesky decomposition, eigenvalue decomposition, eigenvector, lu decomposition, qr decomposition, singular value decomposition" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<center>
|
||||||
|
<hr />
|
||||||
|
[ <a href="index.php">index.php</a> ] [ <a href="docs.php">docs.php</a> ] [ <a href="package.php">package.php</a> ] [ <a href="test.php">test.php</a> ] [ <a href="example.php">example.php</a> ] [ <a href="download.php">download.php</a> ]
|
||||||
|
<hr />
|
||||||
|
</center>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
include_once "includes/header.php";
|
||||||
|
include_once "includes/navbar.php";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
JAMA is a proposed standard matrix class for Java. The JAMA introduction
|
||||||
|
describes "JAMA : A Java Matrix Package" in this way:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
JAMA is a basic linear algebra package for Java. It provides user-level classes for
|
||||||
|
constructing and manipulating real, dense matrices. It is meant to provide sufficient
|
||||||
|
functionality for routine problems, packaged in a way that is natural and understandable
|
||||||
|
to non-experts. It is intended to serve as the standard matrix class for Java, and
|
||||||
|
will be proposed as such to the Java Grande Forum and then to Sun. A straightforward
|
||||||
|
public-domain reference implementation has been developed by the MathWorks and NIST as
|
||||||
|
a strawman for such a class. We are releasing this version in order to obtain public
|
||||||
|
comment. There is no guarantee that future versions of JAMA will be compatible with this one.
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The development team below has successfully ported the JAMA API to PHP. You can explore
|
||||||
|
this site to learn more about this project and it's current development status.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
include_once "includes/credits.php";
|
||||||
|
include_once "includes/footer.php";
|
||||||
|
?>
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
include_once "includes/header.php";
|
||||||
|
include_once "includes/navbar.php";
|
||||||
|
?>
|
||||||
|
<p>
|
||||||
|
Source Listing:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<?php
|
||||||
|
chdir("../");
|
||||||
|
$files = glob("*.php");
|
||||||
|
$files = array_merge($files, glob("util/*.php"));
|
||||||
|
foreach ($files as $fileName) {
|
||||||
|
?>
|
||||||
|
<li><a href="package.php?view=<?php echo sha1($fileName);?>"><?php echo $fileName;?></a> - <?php echo date ("F d Y - g:i a", filemtime($fileName));?></li>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ul>
|
||||||
|
<?php
|
||||||
|
if( isset($_REQUEST['view']) ) {
|
||||||
|
$hash = $_REQUEST['view'];
|
||||||
|
$n = array_search($hash, array_map(sha1, $files));
|
||||||
|
$fileName = $files[$n];
|
||||||
|
?>
|
||||||
|
<hr />
|
||||||
|
Viewing: <?php echo $fileName;?>
|
||||||
|
<hr />
|
||||||
|
<?php
|
||||||
|
highlight_file($fileName);
|
||||||
|
?>
|
||||||
|
<hr />
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
include_once "includes/footer.php";
|
||||||
|
?>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
include_once "includes/header.php";
|
||||||
|
include_once "includes/navbar.php";
|
||||||
|
?>
|
||||||
|
<p>
|
||||||
|
The first script your should run when you install Jama is the TestMatrix.php script.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This will run the unit tests for methods in the <code>Matrix.php</code> class. Because
|
||||||
|
the Matrix.php class can be used to invoke all the decomposition methods the <code>TestMatrix.php</code>
|
||||||
|
script is a test suite for the whole Jama package.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The original <code>TestMatrix.java</code> code uses try/catch error handling. We will
|
||||||
|
eventually create a build of JAMA that will take advantage of PHP5's new try/catch error
|
||||||
|
handling capabilities. This will improve our ability to replicate all the unit tests that
|
||||||
|
appeared in the original (except for some print methods that may not be worth porting).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You can <a href='../test/TestMatrix.php'>run the TestMatrix.php script</a> to see what
|
||||||
|
unit tests are currently implemented. The source of the <code>TestMatrix.php</code> script
|
||||||
|
is provided below. It is worth studying carefully for an example of how to do matrix algebra
|
||||||
|
programming with Jama.
|
||||||
|
</p>
|
||||||
|
<?php
|
||||||
|
highlight_file("../test/TestMatrix.php");
|
||||||
|
include_once "includes/footer.php";
|
||||||
|
?>
|
|
@ -0,0 +1,116 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* quadratic (p-o)'S'S(p-o)
|
||||||
|
* solve for o, S
|
||||||
|
* S is a single scale factor
|
||||||
|
*/
|
||||||
|
class LMQuadTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array[] $x
|
||||||
|
* @param array[] $a
|
||||||
|
*/
|
||||||
|
function val($x, $a) {
|
||||||
|
if (count($a) != 3) die ("Wrong number of elements in array a");
|
||||||
|
if (count($x) != 2) die ("Wrong number of elements in array x");
|
||||||
|
|
||||||
|
$ox = $a[0];
|
||||||
|
$oy = $a[1];
|
||||||
|
$s = $a[2];
|
||||||
|
|
||||||
|
$sdx = $s * ($x[0] - $ox);
|
||||||
|
$sdy = $s * ($x[1] - $oy);
|
||||||
|
|
||||||
|
return ($sdx * $sdx) + ($sdy * $sdy);
|
||||||
|
} // function val()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* z = (p-o)'S'S(p-o)
|
||||||
|
* dz/dp = 2S'S(p-o)
|
||||||
|
*
|
||||||
|
* z = (s*(px-ox))^2 + (s*(py-oy))^2
|
||||||
|
* dz/dox = -2(s*(px-ox))*s
|
||||||
|
* dz/ds = 2*s*[(px-ox)^2 + (py-oy)^2]
|
||||||
|
*
|
||||||
|
* z = (s*dx)^2 + (s*dy)^2
|
||||||
|
* dz/ds = 2(s*dx)*dx + 2(s*dy)*dy
|
||||||
|
*
|
||||||
|
* @param array[] $x
|
||||||
|
* @param array[] $a
|
||||||
|
* @param int $a_k
|
||||||
|
* @param array[] $a
|
||||||
|
*/
|
||||||
|
function grad($x, $a, $a_k) {
|
||||||
|
if (count($a) != 3) die ("Wrong number of elements in array a");
|
||||||
|
if (count($x) != 2) die ("Wrong number of elements in array x");
|
||||||
|
if ($a_k < 3) die ("a_k=".$a_k);
|
||||||
|
|
||||||
|
$ox = $a[0];
|
||||||
|
$oy = $a[1];
|
||||||
|
$s = $a[2];
|
||||||
|
|
||||||
|
$dx = ($x[0] - $ox);
|
||||||
|
$dy = ($x[1] - $oy);
|
||||||
|
|
||||||
|
if ($a_k == 0)
|
||||||
|
return -2.*$s*$s*$dx;
|
||||||
|
elseif ($a_k == 1)
|
||||||
|
return -2.*$s*$s*$dy;
|
||||||
|
else
|
||||||
|
return 2.*$s*($dx*$dx + $dy*$dy);
|
||||||
|
} // function grad()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[] $a
|
||||||
|
*/
|
||||||
|
function initial() {
|
||||||
|
$a[0] = 0.05;
|
||||||
|
$a[1] = 0.1;
|
||||||
|
$a[2] = 1.0;
|
||||||
|
|
||||||
|
return $a;
|
||||||
|
} // function initial()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Object[] $a
|
||||||
|
*/
|
||||||
|
function testdata() {
|
||||||
|
$npts = 25;
|
||||||
|
|
||||||
|
$a[0] = 0.;
|
||||||
|
$a[1] = 0.;
|
||||||
|
$a[2] = 0.9;
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
for ($r = -2; $r <= 2; ++$r) {
|
||||||
|
for ($c = -2; $c <= 2; ++$c) {
|
||||||
|
$x[$i][0] = $c;
|
||||||
|
$x[$i][1] = $r;
|
||||||
|
$y[$i] = $this->val($x[$i], $a);
|
||||||
|
print("Quad ".$c.",".$r." -> ".$y[$i]."<br />");
|
||||||
|
$s[$i] = 1.;
|
||||||
|
++$i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print("quad x= ");
|
||||||
|
|
||||||
|
$qx = new Matrix($x);
|
||||||
|
$qx->print(10, 2);
|
||||||
|
|
||||||
|
print("quad y= ");
|
||||||
|
$qy = new Matrix($y, $npts);
|
||||||
|
$qy->print(10, 2);
|
||||||
|
|
||||||
|
$o[0] = $x;
|
||||||
|
$o[1] = $a;
|
||||||
|
$o[2] = $y;
|
||||||
|
$o[3] = $s;
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
} // function testdata()
|
||||||
|
|
||||||
|
} // class LMQuadTest
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once "../Matrix.php";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given n points (x0,y0)...(xn-1,yn-1), the following methid computes
|
||||||
|
* the polynomial factors of the n-1't degree polynomial passing through
|
||||||
|
* the n points.
|
||||||
|
*
|
||||||
|
* Example: Passing in three points (2,3) (1,4) and (3,7) will produce
|
||||||
|
* the results [2.5, -8.5, 10] which means that the points are on the
|
||||||
|
* curve y = 2.5x² - 8.5x + 10.
|
||||||
|
*
|
||||||
|
* @see http://geosoft.no/software/lagrange/LagrangeInterpolation.java.html
|
||||||
|
* @author Jacob Dreyer
|
||||||
|
* @author Paul Meagher (port to PHP and minor changes)
|
||||||
|
*
|
||||||
|
* @param x[] float
|
||||||
|
* @param y[] float
|
||||||
|
*/
|
||||||
|
class LagrangeInterpolation {
|
||||||
|
|
||||||
|
public function findPolynomialFactors($x, $y) {
|
||||||
|
$n = count($x);
|
||||||
|
|
||||||
|
$data = array(); // double[n][n];
|
||||||
|
$rhs = array(); // double[n];
|
||||||
|
|
||||||
|
for ($i = 0; $i < $n; ++$i) {
|
||||||
|
$v = 1;
|
||||||
|
for ($j = 0; $j < $n; ++$j) {
|
||||||
|
$data[$i][$n-$j-1] = $v;
|
||||||
|
$v *= $x[$i];
|
||||||
|
}
|
||||||
|
$rhs[$i] = $y[$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solve m * s = b
|
||||||
|
$m = new Matrix($data);
|
||||||
|
$b = new Matrix($rhs, $n);
|
||||||
|
|
||||||
|
$s = $m->solve($b);
|
||||||
|
|
||||||
|
return $s->getRowPackedCopy();
|
||||||
|
} // function findPolynomialFactors()
|
||||||
|
|
||||||
|
} // class LagrangeInterpolation
|
||||||
|
|
||||||
|
|
||||||
|
$x = array(2.0, 1.0, 3.0);
|
||||||
|
$y = array(3.0, 4.0, 7.0);
|
||||||
|
|
||||||
|
$li = new LagrangeInterpolation;
|
||||||
|
$f = $li->findPolynomialFactors($x, $y);
|
||||||
|
|
||||||
|
|
||||||
|
for ($i = 0; $i < 3; ++$i) {
|
||||||
|
echo $f[$i]."<br />";
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once "../Matrix.php";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given n points (x0,y0)...(xn-1,yn-1), the following method computes
|
||||||
|
* the polynomial factors of the n-1't degree polynomial passing through
|
||||||
|
* the n points.
|
||||||
|
*
|
||||||
|
* Example: Passing in three points (2,3) (1,4) and (3,7) will produce
|
||||||
|
* the results [2.5, -8.5, 10] which means that the points are on the
|
||||||
|
* curve y = 2.5x² - 8.5x + 10.
|
||||||
|
*
|
||||||
|
* @see http://geosoft.no/software/lagrange/LagrangeInterpolation.java.html
|
||||||
|
* @see http://source.freehep.org/jcvsweb/ilc/LCSIM/wdview/lcsim/src/org/lcsim/fit/polynomial/PolynomialFitter.java
|
||||||
|
* @author Jacob Dreyer
|
||||||
|
* @author Paul Meagher (port to PHP and minor changes)
|
||||||
|
*
|
||||||
|
* @param x[] float
|
||||||
|
* @param y[] float
|
||||||
|
*/
|
||||||
|
class LagrangeInterpolation {
|
||||||
|
|
||||||
|
public function findPolynomialFactors($x, $y) {
|
||||||
|
$n = count($x);
|
||||||
|
|
||||||
|
$data = array(); // double[n][n];
|
||||||
|
$rhs = array(); // double[n];
|
||||||
|
|
||||||
|
for ($i = 0; $i < $n; ++$i) {
|
||||||
|
$v = 1;
|
||||||
|
for ($j = 0; $j < $n; ++$j) {
|
||||||
|
$data[$i][$n-$j-1] = $v;
|
||||||
|
$v *= $x[$i];
|
||||||
|
}
|
||||||
|
$rhs[$i] = $y[$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solve m * s = b
|
||||||
|
$m = new Matrix($data);
|
||||||
|
$b = new Matrix($rhs, $n);
|
||||||
|
|
||||||
|
$s = $m->solve($b);
|
||||||
|
|
||||||
|
return $s->getRowPackedCopy();
|
||||||
|
} // function findPolynomialFactors()
|
||||||
|
|
||||||
|
} // class LagrangeInterpolation
|
||||||
|
|
||||||
|
|
||||||
|
$x = array(2.0, 1.0, 3.0);
|
||||||
|
$y = array(3.0, 4.0, 7.0);
|
||||||
|
|
||||||
|
$li = new LagrangeInterpolation;
|
||||||
|
$f = $li->findPolynomialFactors($x, $y);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 3; ++$i) {
|
||||||
|
echo $f[$i]."<br />";
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Levenberg-Marquardt in PHP
|
||||||
|
|
||||||
|
// http://www.idiom.com/~zilla/Computer/Javanumeric/LM.java
|
||||||
|
|
||||||
|
class LevenbergMarquardt {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the current sum-squared-error
|
||||||
|
*
|
||||||
|
* Chi-squared is the distribution of squared Gaussian errors,
|
||||||
|
* thus the name.
|
||||||
|
*
|
||||||
|
* @param double[][] $x
|
||||||
|
* @param double[] $a
|
||||||
|
* @param double[] $y,
|
||||||
|
* @param double[] $s,
|
||||||
|
* @param object $f
|
||||||
|
*/
|
||||||
|
function chiSquared($x, $a, $y, $s, $f) {
|
||||||
|
$npts = count($y);
|
||||||
|
$sum = 0.0;
|
||||||
|
|
||||||
|
for ($i = 0; $i < $npts; ++$i) {
|
||||||
|
$d = $y[$i] - $f->val($x[$i], $a);
|
||||||
|
$d = $d / $s[$i];
|
||||||
|
$sum = $sum + ($d*$d);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sum;
|
||||||
|
} // function chiSquared()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimize E = sum {(y[k] - f(x[k],a)) / s[k]}^2
|
||||||
|
* The individual errors are optionally scaled by s[k].
|
||||||
|
* Note that LMfunc implements the value and gradient of f(x,a),
|
||||||
|
* NOT the value and gradient of E with respect to a!
|
||||||
|
*
|
||||||
|
* @param x array of domain points, each may be multidimensional
|
||||||
|
* @param y corresponding array of values
|
||||||
|
* @param a the parameters/state of the model
|
||||||
|
* @param vary false to indicate the corresponding a[k] is to be held fixed
|
||||||
|
* @param s2 sigma^2 for point i
|
||||||
|
* @param lambda blend between steepest descent (lambda high) and
|
||||||
|
* jump to bottom of quadratic (lambda zero).
|
||||||
|
* Start with 0.001.
|
||||||
|
* @param termepsilon termination accuracy (0.01)
|
||||||
|
* @param maxiter stop and return after this many iterations if not done
|
||||||
|
* @param verbose set to zero (no prints), 1, 2
|
||||||
|
*
|
||||||
|
* @return the new lambda for future iterations.
|
||||||
|
* Can use this and maxiter to interleave the LM descent with some other
|
||||||
|
* task, setting maxiter to something small.
|
||||||
|
*/
|
||||||
|
function solve($x, $a, $y, $s, $vary, $f, $lambda, $termepsilon, $maxiter, $verbose) {
|
||||||
|
$npts = count($y);
|
||||||
|
$nparm = count($a);
|
||||||
|
|
||||||
|
if ($verbose > 0) {
|
||||||
|
print("solve x[".count($x)."][".count($x[0])."]");
|
||||||
|
print(" a[".count($a)."]");
|
||||||
|
println(" y[".count(length)."]");
|
||||||
|
}
|
||||||
|
|
||||||
|
$e0 = $this->chiSquared($x, $a, $y, $s, $f);
|
||||||
|
|
||||||
|
//double lambda = 0.001;
|
||||||
|
$done = false;
|
||||||
|
|
||||||
|
// g = gradient, H = hessian, d = step to minimum
|
||||||
|
// H d = -g, solve for d
|
||||||
|
$H = array();
|
||||||
|
$g = array();
|
||||||
|
|
||||||
|
//double[] d = new double[nparm];
|
||||||
|
|
||||||
|
$oos2 = array();
|
||||||
|
|
||||||
|
for($i = 0; $i < $npts; ++$i) {
|
||||||
|
$oos2[$i] = 1./($s[$i]*$s[$i]);
|
||||||
|
}
|
||||||
|
$iter = 0;
|
||||||
|
$term = 0; // termination count test
|
||||||
|
|
||||||
|
do {
|
||||||
|
++$iter;
|
||||||
|
|
||||||
|
// hessian approximation
|
||||||
|
for( $r = 0; $r < $nparm; ++$r) {
|
||||||
|
for( $c = 0; $c < $nparm; ++$c) {
|
||||||
|
for( $i = 0; $i < $npts; ++$i) {
|
||||||
|
if ($i == 0) $H[$r][$c] = 0.;
|
||||||
|
$xi = $x[$i];
|
||||||
|
$H[$r][$c] += ($oos2[$i] * $f->grad($xi, $a, $r) * $f->grad($xi, $a, $c));
|
||||||
|
} //npts
|
||||||
|
} //c
|
||||||
|
} //r
|
||||||
|
|
||||||
|
// boost diagonal towards gradient descent
|
||||||
|
for( $r = 0; $r < $nparm; ++$r)
|
||||||
|
$H[$r][$r] *= (1. + $lambda);
|
||||||
|
|
||||||
|
// gradient
|
||||||
|
for( $r = 0; $r < $nparm; ++$r) {
|
||||||
|
for( $i = 0; $i < $npts; ++$i) {
|
||||||
|
if ($i == 0) $g[$r] = 0.;
|
||||||
|
$xi = $x[$i];
|
||||||
|
$g[$r] += ($oos2[$i] * ($y[$i]-$f->val($xi,$a)) * $f->grad($xi, $a, $r));
|
||||||
|
}
|
||||||
|
} //npts
|
||||||
|
|
||||||
|
// scale (for consistency with NR, not necessary)
|
||||||
|
if ($false) {
|
||||||
|
for( $r = 0; $r < $nparm; ++$r) {
|
||||||
|
$g[$r] = -0.5 * $g[$r];
|
||||||
|
for( $c = 0; $c < $nparm; ++$c) {
|
||||||
|
$H[$r][$c] *= 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// solve H d = -g, evaluate error at new location
|
||||||
|
//double[] d = DoubleMatrix.solve(H, g);
|
||||||
|
// double[] d = (new Matrix(H)).lu().solve(new Matrix(g, nparm)).getRowPackedCopy();
|
||||||
|
//double[] na = DoubleVector.add(a, d);
|
||||||
|
// double[] na = (new Matrix(a, nparm)).plus(new Matrix(d, nparm)).getRowPackedCopy();
|
||||||
|
// double e1 = chiSquared(x, na, y, s, f);
|
||||||
|
|
||||||
|
// if (verbose > 0) {
|
||||||
|
// System.out.println("\n\niteration "+iter+" lambda = "+lambda);
|
||||||
|
// System.out.print("a = ");
|
||||||
|
// (new Matrix(a, nparm)).print(10, 2);
|
||||||
|
// if (verbose > 1) {
|
||||||
|
// System.out.print("H = ");
|
||||||
|
// (new Matrix(H)).print(10, 2);
|
||||||
|
// System.out.print("g = ");
|
||||||
|
// (new Matrix(g, nparm)).print(10, 2);
|
||||||
|
// System.out.print("d = ");
|
||||||
|
// (new Matrix(d, nparm)).print(10, 2);
|
||||||
|
// }
|
||||||
|
// System.out.print("e0 = " + e0 + ": ");
|
||||||
|
// System.out.print("moved from ");
|
||||||
|
// (new Matrix(a, nparm)).print(10, 2);
|
||||||
|
// System.out.print("e1 = " + e1 + ": ");
|
||||||
|
// if (e1 < e0) {
|
||||||
|
// System.out.print("to ");
|
||||||
|
// (new Matrix(na, nparm)).print(10, 2);
|
||||||
|
// } else {
|
||||||
|
// System.out.println("move rejected");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// termination test (slightly different than NR)
|
||||||
|
// if (Math.abs(e1-e0) > termepsilon) {
|
||||||
|
// term = 0;
|
||||||
|
// } else {
|
||||||
|
// term++;
|
||||||
|
// if (term == 4) {
|
||||||
|
// System.out.println("terminating after " + iter + " iterations");
|
||||||
|
// done = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (iter >= maxiter) done = true;
|
||||||
|
|
||||||
|
// in the C++ version, found that changing this to e1 >= e0
|
||||||
|
// was not a good idea. See comment there.
|
||||||
|
//
|
||||||
|
// if (e1 > e0 || Double.isNaN(e1)) { // new location worse than before
|
||||||
|
// lambda *= 10.;
|
||||||
|
// } else { // new location better, accept new parameters
|
||||||
|
// lambda *= 0.1;
|
||||||
|
// e0 = e1;
|
||||||
|
// // simply assigning a = na will not get results copied back to caller
|
||||||
|
// for( int i = 0; i < nparm; i++ ) {
|
||||||
|
// if (vary[i]) a[i] = na[i];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
} while(!$done);
|
||||||
|
|
||||||
|
return $lambda;
|
||||||
|
} // function solve()
|
||||||
|
|
||||||
|
} // class LevenbergMarquardt
|
|
@ -0,0 +1,182 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package JAMA
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once "../Matrix.php";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example of use of Matrix Class, featuring magic squares.
|
||||||
|
*/
|
||||||
|
class MagicSquareExample {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate magic square test matrix.
|
||||||
|
* @param int n dimension of matrix
|
||||||
|
*/
|
||||||
|
function magic($n) {
|
||||||
|
|
||||||
|
// Odd order
|
||||||
|
|
||||||
|
if (($n % 2) == 1) {
|
||||||
|
$a = ($n+1)/2;
|
||||||
|
$b = ($n+1);
|
||||||
|
for ($j = 0; $j < $n; ++$j)
|
||||||
|
for ($i = 0; $i < $n; ++$i)
|
||||||
|
$M[$i][$j] = $n*(($i+$j+$a) % $n) + (($i+2*$j+$b) % $n) + 1;
|
||||||
|
|
||||||
|
// Doubly Even Order
|
||||||
|
|
||||||
|
} else if (($n % 4) == 0) {
|
||||||
|
for ($j = 0; $j < $n; ++$j) {
|
||||||
|
for ($i = 0; $i < $n; ++$i) {
|
||||||
|
if ((($i+1)/2)%2 == (($j+1)/2)%2)
|
||||||
|
$M[$i][$j] = $n*$n-$n*$i-$j;
|
||||||
|
else
|
||||||
|
$M[$i][$j] = $n*$i+$j+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Singly Even Order
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$p = $n/2;
|
||||||
|
$k = ($n-2)/4;
|
||||||
|
$A = $this->magic($p);
|
||||||
|
$M = array();
|
||||||
|
for ($j = 0; $j < $p; ++$j) {
|
||||||
|
for ($i = 0; $i < $p; ++$i) {
|
||||||
|
$aij = $A->get($i,$j);
|
||||||
|
$M[$i][$j] = $aij;
|
||||||
|
$M[$i][$j+$p] = $aij + 2*$p*$p;
|
||||||
|
$M[$i+$p][$j] = $aij + 3*$p*$p;
|
||||||
|
$M[$i+$p][$j+$p] = $aij + $p*$p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 0; $i < $p; ++$i) {
|
||||||
|
for ($j = 0; $j < $k; ++$j) {
|
||||||
|
$t = $M[$i][$j];
|
||||||
|
$M[$i][$j] = $M[$i+$p][$j];
|
||||||
|
$M[$i+$p][$j] = $t;
|
||||||
|
}
|
||||||
|
for ($j = $n-$k+1; $j < $n; ++$j) {
|
||||||
|
$t = $M[$i][$j];
|
||||||
|
$M[$i][$j] = $M[$i+$p][$j];
|
||||||
|
$M[$i+$p][$j] = $t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$t = $M[$k][0]; $M[$k][0] = $M[$k+$p][0]; $M[$k+$p][0] = $t;
|
||||||
|
$t = $M[$k][$k]; $M[$k][$k] = $M[$k+$p][$k]; $M[$k+$p][$k] = $t;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Matrix($M);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple function to replicate PHP 5 behaviour
|
||||||
|
*/
|
||||||
|
function microtime_float() {
|
||||||
|
list($usec, $sec) = explode(" ", microtime());
|
||||||
|
return ((float)$usec + (float)$sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests LU, QR, SVD and symmetric Eig decompositions.
|
||||||
|
*
|
||||||
|
* n = order of magic square.
|
||||||
|
* trace = diagonal sum, should be the magic sum, (n^3 + n)/2.
|
||||||
|
* max_eig = maximum eigenvalue of (A + A')/2, should equal trace.
|
||||||
|
* rank = linear algebraic rank, should equal n if n is odd,
|
||||||
|
* be less than n if n is even.
|
||||||
|
* cond = L_2 condition number, ratio of singular values.
|
||||||
|
* lu_res = test of LU factorization, norm1(L*U-A(p,:))/(n*eps).
|
||||||
|
* qr_res = test of QR factorization, norm1(Q*R-A)/(n*eps).
|
||||||
|
*/
|
||||||
|
function main() {
|
||||||
|
?>
|
||||||
|
<p>Test of Matrix Class, using magic squares.</p>
|
||||||
|
<p>See MagicSquareExample.main() for an explanation.</p>
|
||||||
|
<table border='1' cellspacing='0' cellpadding='4'>
|
||||||
|
<tr>
|
||||||
|
<th>n</th>
|
||||||
|
<th>trace</th>
|
||||||
|
<th>max_eig</th>
|
||||||
|
<th>rank</th>
|
||||||
|
<th>cond</th>
|
||||||
|
<th>lu_res</th>
|
||||||
|
<th>qr_res</th>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
$start_time = $this->microtime_float();
|
||||||
|
$eps = pow(2.0,-52.0);
|
||||||
|
for ($n = 3; $n <= 6; ++$n) {
|
||||||
|
echo "<tr>";
|
||||||
|
|
||||||
|
echo "<td align='right'>$n</td>";
|
||||||
|
|
||||||
|
$M = $this->magic($n);
|
||||||
|
$t = (int) $M->trace();
|
||||||
|
|
||||||
|
echo "<td align='right'>$t</td>";
|
||||||
|
|
||||||
|
$O = $M->plus($M->transpose());
|
||||||
|
$E = new EigenvalueDecomposition($O->times(0.5));
|
||||||
|
$d = $E->getRealEigenvalues();
|
||||||
|
|
||||||
|
echo "<td align='right'>".$d[$n-1]."</td>";
|
||||||
|
|
||||||
|
$r = $M->rank();
|
||||||
|
|
||||||
|
echo "<td align='right'>".$r."</td>";
|
||||||
|
|
||||||
|
$c = $M->cond();
|
||||||
|
|
||||||
|
if ($c < 1/$eps)
|
||||||
|
echo "<td align='right'>".sprintf("%.3f",$c)."</td>";
|
||||||
|
else
|
||||||
|
echo "<td align='right'>Inf</td>";
|
||||||
|
|
||||||
|
$LU = new LUDecomposition($M);
|
||||||
|
$L = $LU->getL();
|
||||||
|
$U = $LU->getU();
|
||||||
|
$p = $LU->getPivot();
|
||||||
|
// Java version: R = L.times(U).minus(M.getMatrix(p,0,n-1));
|
||||||
|
$S = $L->times($U);
|
||||||
|
$R = $S->minus($M->getMatrix($p,0,$n-1));
|
||||||
|
$res = $R->norm1()/($n*$eps);
|
||||||
|
|
||||||
|
echo "<td align='right'>".sprintf("%.3f",$res)."</td>";
|
||||||
|
|
||||||
|
$QR = new QRDecomposition($M);
|
||||||
|
$Q = $QR->getQ();
|
||||||
|
$R = $QR->getR();
|
||||||
|
$S = $Q->times($R);
|
||||||
|
$R = $S->minus($M);
|
||||||
|
$res = $R->norm1()/($n*$eps);
|
||||||
|
|
||||||
|
echo "<td align='right'>".sprintf("%.3f",$res)."</td>";
|
||||||
|
|
||||||
|
echo "</tr>";
|
||||||
|
|
||||||
|
}
|
||||||
|
echo "<table>";
|
||||||
|
echo "<br />";
|
||||||
|
|
||||||
|
$stop_time = $this->microtime_float();
|
||||||
|
$etime = $stop_time - $start_time;
|
||||||
|
|
||||||
|
echo "<p>Elapsed time is ". sprintf("%.4f",$etime) ." seconds.</p>";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$magic = new MagicSquareExample();
|
||||||
|
$magic->main();
|
||||||
|
|
||||||
|
?>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,263 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package JAMA
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once '../Matrix.php';
|
||||||
|
require_once 'Stats.php';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example of use of Matrix Class, featuring magic squares.
|
||||||
|
*/
|
||||||
|
class Benchmark {
|
||||||
|
public $stat;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple function to replicate PHP 5 behaviour
|
||||||
|
*/
|
||||||
|
function microtime_float() {
|
||||||
|
list($usec, $sec) = explode(" ", microtime());
|
||||||
|
|
||||||
|
return ((float)$usec + (float)$sec);
|
||||||
|
} // function microtime_float()
|
||||||
|
|
||||||
|
|
||||||
|
function displayStats($times = null) {
|
||||||
|
$this->stat->setData($times);
|
||||||
|
$stats = $this->stat->calcFull();
|
||||||
|
|
||||||
|
echo '<table style="margin-left:32px;">';
|
||||||
|
echo '<tr><td style="text-align:right;"><b>n:</b><td style="text-align:right;">' . $stats['count'] . ' </td></tr>';
|
||||||
|
echo '<tr><td style="text-align:right;"><b>Mean:</b><td style="text-align:right;">' . $stats['mean'] . ' </td></tr>';
|
||||||
|
echo '<tr><td style="text-align:right;"><b>Min.:</b><td style="text-align:right;">' . $stats['min'] . ' </td></tr>';
|
||||||
|
echo '<tr><td style="text-align:right;"><b>Max.:</b><td style="text-align:right;">' . $stats['max'] . ' </td></tr>';
|
||||||
|
echo '<tr><td style="text-align:right;"><b>σ:</b><td style="text-align:right;">' . $stats['stdev'] . ' </td></tr>';
|
||||||
|
echo '<tr><td style="text-align:right;"><b>Variance:</b><td style="text-align:right;">' . $stats['variance'] . ' </td></tr>';
|
||||||
|
echo '<tr><td style="text-align:right;"><b>Range:</b><td style="text-align:right;">' . $stats['range'] . ' </td></tr>';
|
||||||
|
echo '</table>';
|
||||||
|
|
||||||
|
return $stats;
|
||||||
|
} // function displayStats()
|
||||||
|
|
||||||
|
|
||||||
|
function runEig($n = 4, $t = 100) {
|
||||||
|
$times = array();
|
||||||
|
|
||||||
|
for ($i = 0; $i < $t; ++$i) {
|
||||||
|
$M = Matrix::random($n, $n);
|
||||||
|
$start_time = $this->microtime_float();
|
||||||
|
$E = new EigenvalueDecomposition($M);
|
||||||
|
$stop_time = $this->microtime_float();
|
||||||
|
$times[] = $stop_time - $start_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $times;
|
||||||
|
} // function runEig()
|
||||||
|
|
||||||
|
|
||||||
|
function runLU($n = 4, $t = 100) {
|
||||||
|
$times = array();
|
||||||
|
|
||||||
|
for ($i = 0; $i < $t; ++$i) {
|
||||||
|
$M = Matrix::random($n, $n);
|
||||||
|
$start_time = $this->microtime_float();
|
||||||
|
$E = new LUDecomposition($M);
|
||||||
|
$stop_time = $this->microtime_float();
|
||||||
|
$times[] = $stop_time - $start_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $times;
|
||||||
|
} // function runLU()
|
||||||
|
|
||||||
|
|
||||||
|
function runQR($n = 4, $t = 100) {
|
||||||
|
$times = array();
|
||||||
|
|
||||||
|
for ($i = 0; $i < $t; ++$i) {
|
||||||
|
$M = Matrix::random($n, $n);
|
||||||
|
$start_time = $this->microtime_float();
|
||||||
|
$E = new QRDecomposition($M);
|
||||||
|
$stop_time = $this->microtime_float();
|
||||||
|
$times[] = $stop_time - $start_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $times;
|
||||||
|
} // function runQR()
|
||||||
|
|
||||||
|
|
||||||
|
function runCholesky($n = 4, $t = 100) {
|
||||||
|
$times = array();
|
||||||
|
|
||||||
|
for ($i = 0; $i < $t; ++$i) {
|
||||||
|
$M = Matrix::random($n, $n);
|
||||||
|
$start_time = $this->microtime_float();
|
||||||
|
$E = new CholeskyDecomposition($M);
|
||||||
|
$stop_time = $this->microtime_float();
|
||||||
|
$times[] = $stop_time - $start_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $times;
|
||||||
|
} // function runCholesky()
|
||||||
|
|
||||||
|
|
||||||
|
function runSVD($n = 4, $t = 100) {
|
||||||
|
$times = array();
|
||||||
|
|
||||||
|
for ($i = 0; $i < $t; ++$i) {
|
||||||
|
$M = Matrix::random($n, $n);
|
||||||
|
$start_time = $this->microtime_float();
|
||||||
|
$E = new SingularValueDecomposition($M);
|
||||||
|
$stop_time = $this->microtime_float();
|
||||||
|
$times[] = $stop_time - $start_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $times;
|
||||||
|
} // function runSVD()
|
||||||
|
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
$n = 8;
|
||||||
|
$t = 16;
|
||||||
|
$sum = 0;
|
||||||
|
echo "<b>Cholesky decomposition: $t random {$n}x{$n} matrices</b><br />";
|
||||||
|
$r = $this->displayStats($this->runCholesky($n, $t));
|
||||||
|
$sum += $r['mean'] * $n;
|
||||||
|
|
||||||
|
echo '<hr />';
|
||||||
|
|
||||||
|
echo "<b>Eigenvalue decomposition: $t random {$n}x{$n} matrices</b><br />";
|
||||||
|
$r = $this->displayStats($this->runEig($n, $t));
|
||||||
|
$sum += $r['mean'] * $n;
|
||||||
|
|
||||||
|
echo '<hr />';
|
||||||
|
|
||||||
|
echo "<b>LU decomposition: $t random {$n}x{$n} matrices</b><br />";
|
||||||
|
$r = $this->displayStats($this->runLU($n, $t));
|
||||||
|
$sum += $r['mean'] * $n;
|
||||||
|
|
||||||
|
echo '<hr />';
|
||||||
|
|
||||||
|
echo "<b>QR decomposition: $t random {$n}x{$n} matrices</b><br />";
|
||||||
|
$r = $this->displayStats($this->runQR($n, $t));
|
||||||
|
$sum += $r['mean'] * $n;
|
||||||
|
|
||||||
|
echo '<hr />';
|
||||||
|
|
||||||
|
echo "<b>Singular Value decomposition: $t random {$n}x{$n} matrices</b><br />";
|
||||||
|
$r = $this->displayStats($this->runSVD($n, $t));
|
||||||
|
$sum += $r['mean'] * $n;
|
||||||
|
|
||||||
|
return $sum;
|
||||||
|
} // function run()
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->stat = new Base();
|
||||||
|
} // function Benchmark()
|
||||||
|
|
||||||
|
} // class Benchmark (end MagicSquareExample)
|
||||||
|
|
||||||
|
|
||||||
|
$benchmark = new Benchmark();
|
||||||
|
|
||||||
|
switch($_REQUEST['decomposition']) {
|
||||||
|
case 'cholesky':
|
||||||
|
$m = array();
|
||||||
|
for ($i = 2; $i <= 8; $i *= 2) {
|
||||||
|
$t = 32 / $i;
|
||||||
|
echo "<b>Cholesky decomposition: $t random {$i}x{$i} matrices</b><br />";
|
||||||
|
$s = $benchmark->displayStats($benchmark->runCholesky($i, $t));
|
||||||
|
$m[$i] = $s['mean'];
|
||||||
|
echo "<br />";
|
||||||
|
}
|
||||||
|
echo '<pre>';
|
||||||
|
foreach($m as $x => $y) {
|
||||||
|
echo "$x\t" . 1000*$y . "\n";
|
||||||
|
}
|
||||||
|
echo '</pre>';
|
||||||
|
break;
|
||||||
|
case 'eigenvalue':
|
||||||
|
$m = array();
|
||||||
|
for ($i = 2; $i <= 8; $i *= 2) {
|
||||||
|
$t = 32 / $i;
|
||||||
|
echo "<b>Eigenvalue decomposition: $t random {$i}x{$i} matrices</b><br />";
|
||||||
|
$s = $benchmark->displayStats($benchmark->runEig($i, $t));
|
||||||
|
$m[$i] = $s['mean'];
|
||||||
|
echo "<br />";
|
||||||
|
}
|
||||||
|
echo '<pre>';
|
||||||
|
foreach($m as $x => $y) {
|
||||||
|
echo "$x\t" . 1000*$y . "\n";
|
||||||
|
}
|
||||||
|
echo '</pre>';
|
||||||
|
break;
|
||||||
|
case 'lu':
|
||||||
|
$m = array();
|
||||||
|
for ($i = 2; $i <= 8; $i *= 2) {
|
||||||
|
$t = 32 / $i;
|
||||||
|
echo "<b>LU decomposition: $t random {$i}x{$i} matrices</b><br />";
|
||||||
|
$s = $benchmark->displayStats($benchmark->runLU($i, $t));
|
||||||
|
$m[$i] = $s['mean'];
|
||||||
|
echo "<br />";
|
||||||
|
}
|
||||||
|
echo '<pre>';
|
||||||
|
foreach($m as $x => $y) {
|
||||||
|
echo "$x\t" . 1000*$y . "\n";
|
||||||
|
}
|
||||||
|
echo '</pre>';
|
||||||
|
break;
|
||||||
|
case 'qr':
|
||||||
|
$m = array();
|
||||||
|
for ($i = 2; $i <= 8; $i *= 2) {
|
||||||
|
$t = 32 / $i;
|
||||||
|
echo "<b>QR decomposition: $t random {$i}x{$i} matrices</b><br />";
|
||||||
|
$s = $benchmark->displayStats($benchmark->runQR($i, $t));
|
||||||
|
$m[$i] = $s['mean'];
|
||||||
|
echo "<br />";
|
||||||
|
}
|
||||||
|
echo '<pre>';
|
||||||
|
foreach($m as $x => $y) {
|
||||||
|
echo "$x\t" . 1000*$y . "\n";
|
||||||
|
}
|
||||||
|
echo '</pre>';
|
||||||
|
break;
|
||||||
|
case 'svd':
|
||||||
|
$m = array();
|
||||||
|
for($i = 2; $i <= 8; $i *= 2) {
|
||||||
|
$t = 32 / $i;
|
||||||
|
echo "<b>Singular value decomposition: $t random {$i}x{$i} matrices</b><br />";
|
||||||
|
$s = $benchmark->displayStats($benchmark->runSVD($i, $t));
|
||||||
|
$m[$i] = $s['mean'];
|
||||||
|
echo "<br />";
|
||||||
|
}
|
||||||
|
echo '<pre>';
|
||||||
|
foreach($m as $x => $y) {
|
||||||
|
echo "$x\t" . 1000*$y . "\n";
|
||||||
|
}
|
||||||
|
echo '</pre>';
|
||||||
|
break;
|
||||||
|
case 'all':
|
||||||
|
$s = $benchmark->run();
|
||||||
|
print("<br /><b>Total<b>: {$s}s<br />");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
?>
|
||||||
|
<ul>
|
||||||
|
<li><a href="benchmark.php?decomposition=all">Complete Benchmark</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="benchmark.php?decomposition=cholesky">Cholesky</a></li>
|
||||||
|
<li><a href="benchmark.php?decomposition=eigenvalue">Eigenvalue</a></li>
|
||||||
|
<li><a href="benchmark.php?decomposition=lu">LU</a></li>
|
||||||
|
<li><a href="benchmark.php?decomposition=qr">QR</a></li>
|
||||||
|
<li><a href="benchmark.php?decomposition=svd">Singular Value</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<?php
|
||||||
|
break;
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
require_once "../Matrix.php";
|
||||||
|
/*
|
||||||
|
* @package JAMA
|
||||||
|
* @author Michael Bommarito
|
||||||
|
* @author Paul Meagher
|
||||||
|
* @version 0.1
|
||||||
|
*
|
||||||
|
* Function to fit an order n polynomial function through
|
||||||
|
* a series of x-y data points using least squares.
|
||||||
|
*
|
||||||
|
* @param $X array x values
|
||||||
|
* @param $Y array y values
|
||||||
|
* @param $n int order of polynomial to be used for fitting
|
||||||
|
* @returns array $coeffs of polynomial coefficients
|
||||||
|
* Pre-Conditions: the system is not underdetermined: sizeof($X) > $n+1
|
||||||
|
*/
|
||||||
|
function polyfit($X, $Y, $n) {
|
||||||
|
for ($i = 0; $i < sizeof($X); ++$i)
|
||||||
|
for ($j = 0; $j <= $n; ++$j)
|
||||||
|
$A[$i][$j] = pow($X[$i], $j);
|
||||||
|
for ($i=0; $i < sizeof($Y); ++$i)
|
||||||
|
$B[$i] = array($Y[$i]);
|
||||||
|
$matrixA = new Matrix($A);
|
||||||
|
$matrixB = new Matrix($B);
|
||||||
|
$C = $matrixA->solve($matrixB);
|
||||||
|
return $C->getMatrix(0, $n, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function printpoly( $C = null ) {
|
||||||
|
for($i = $C->m - 1; $i >= 0; --$i) {
|
||||||
|
$r = $C->get($i, 0);
|
||||||
|
if ( abs($r) <= pow(10, -9) )
|
||||||
|
$r = 0;
|
||||||
|
if ($i == $C->m - 1)
|
||||||
|
echo $r . "x<sup>$i</sup>";
|
||||||
|
else if ($i < $C->m - 1)
|
||||||
|
echo " + " . $r . "x<sup>$i</sup>";
|
||||||
|
else if ($i == 0)
|
||||||
|
echo " + " . $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$X = array(0,1,2,3,4,5);
|
||||||
|
$Y = array(4,3,12,67,228, 579);
|
||||||
|
$points = new Matrix(array($X, $Y));
|
||||||
|
$points->toHTML();
|
||||||
|
printpoly(polyfit($X, $Y, 4));
|
||||||
|
|
||||||
|
echo '<hr />';
|
||||||
|
|
||||||
|
$X = array(0,1,2,3,4,5);
|
||||||
|
$Y = array(1,2,5,10,17, 26);
|
||||||
|
$points = new Matrix(array($X, $Y));
|
||||||
|
$points->toHTML();
|
||||||
|
printpoly(polyfit($X, $Y, 2));
|
||||||
|
|
||||||
|
echo '<hr />';
|
||||||
|
|
||||||
|
$X = array(0,1,2,3,4,5,6);
|
||||||
|
$Y = array(-90,-104,-178,-252,-26, 1160, 4446);
|
||||||
|
$points = new Matrix(array($X, $Y));
|
||||||
|
$points->toHTML();
|
||||||
|
printpoly(polyfit($X, $Y, 5));
|
||||||
|
|
||||||
|
echo '<hr />';
|
||||||
|
|
||||||
|
$X = array(0,1,2,3,4);
|
||||||
|
$Y = array(mt_rand(0, 10), mt_rand(40, 80), mt_rand(240, 400), mt_rand(1800, 2215), mt_rand(8000, 9000));
|
||||||
|
$points = new Matrix(array($X, $Y));
|
||||||
|
$points->toHTML();
|
||||||
|
printpoly(polyfit($X, $Y, 3));
|
||||||
|
?>
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
include "../Matrix.php";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiling of matrix X in [rowWise by colWise] dimension. Tiling
|
||||||
|
* creates a larger matrix than the original data X. Example, if
|
||||||
|
* X is to be tiled in a [3 x 4] manner, then:
|
||||||
|
*
|
||||||
|
* / \
|
||||||
|
* | X X X X |
|
||||||
|
* C = | X X X X |
|
||||||
|
* | X X X X |
|
||||||
|
* \ /
|
||||||
|
*
|
||||||
|
* @param X Matrix
|
||||||
|
* @param rowWise int
|
||||||
|
* @param colWise int
|
||||||
|
* @return Matrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
function tile(&$X, $rowWise, $colWise){
|
||||||
|
|
||||||
|
$xArray = $X->getArray();
|
||||||
|
print_r($xArray);
|
||||||
|
|
||||||
|
$countRow = 0;
|
||||||
|
$countColumn = 0;
|
||||||
|
|
||||||
|
$m = $X->getRowDimension();
|
||||||
|
$n = $X->getColumnDimension();
|
||||||
|
|
||||||
|
if( $rowWise<1 || $colWise<1 ){
|
||||||
|
die("tile : Array index is out-of-bound.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$newRowDim = $m*$rowWise;
|
||||||
|
$newColDim = $n*$colWise;
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
|
||||||
|
for($i=0 ; $i<$newRowDim; ++$i) {
|
||||||
|
|
||||||
|
$holder = array();
|
||||||
|
|
||||||
|
for($j=0 ; $j<$newColDim ; ++$j) {
|
||||||
|
|
||||||
|
$holder[$j] = $xArray[$countRow][$countColumn++];
|
||||||
|
|
||||||
|
// reset the column-index to zero to avoid reference to out-of-bound index in xArray[][]
|
||||||
|
|
||||||
|
if($countColumn == $n) { $countColumn = 0; }
|
||||||
|
|
||||||
|
} // end for
|
||||||
|
|
||||||
|
++$countRow;
|
||||||
|
|
||||||
|
// reset the row-index to zero to avoid reference to out-of-bound index in xArray[][]
|
||||||
|
|
||||||
|
if($countRow == $m) { $countRow = 0; }
|
||||||
|
|
||||||
|
$result[$i] = $holder;
|
||||||
|
|
||||||
|
} // end for
|
||||||
|
|
||||||
|
return new Matrix($result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$X =array(1,2,3,4,5,6,7,8,9);
|
||||||
|
$nRow = 3;
|
||||||
|
$nCol = 3;
|
||||||
|
$tiled_matrix = tile(new Matrix($X), $nRow, $nCol);
|
||||||
|
echo "<pre>";
|
||||||
|
print_r($tiled_matrix);
|
||||||
|
echo "</pre>";
|
||||||
|
?>
|
|
@ -0,0 +1,415 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once "../Matrix.php";
|
||||||
|
|
||||||
|
class TestMatrix {
|
||||||
|
|
||||||
|
function TestMatrix() {
|
||||||
|
|
||||||
|
// define test variables
|
||||||
|
|
||||||
|
$errorCount = 0;
|
||||||
|
$warningCount = 0;
|
||||||
|
$columnwise = array(1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.);
|
||||||
|
$rowwise = array(1.,4.,7.,10.,2.,5.,8.,11.,3.,6.,9.,12.);
|
||||||
|
$avals = array(array(1.,4.,7.,10.),array(2.,5.,8.,11.),array(3.,6.,9.,12.));
|
||||||
|
$rankdef = $avals;
|
||||||
|
$tvals = array(array(1.,2.,3.),array(4.,5.,6.),array(7.,8.,9.),array(10.,11.,12.));
|
||||||
|
$subavals = array(array(5.,8.,11.),array(6.,9.,12.));
|
||||||
|
$rvals = array(array(1.,4.,7.),array(2.,5.,8.,11.),array(3.,6.,9.,12.));
|
||||||
|
$pvals = array(array(1.,1.,1.),array(1.,2.,3.),array(1.,3.,6.));
|
||||||
|
$ivals = array(array(1.,0.,0.,0.),array(0.,1.,0.,0.),array(0.,0.,1.,0.));
|
||||||
|
$evals = array(array(0.,1.,0.,0.),array(1.,0.,2.e-7,0.),array(0.,-2.e-7,0.,1.),array(0.,0.,1.,0.));
|
||||||
|
$square = array(array(166.,188.,210.),array(188.,214.,240.),array(210.,240.,270.));
|
||||||
|
$sqSolution = array(array(13.),array(15.));
|
||||||
|
$condmat = array(array(1.,3.),array(7.,9.));
|
||||||
|
$rows = 3;
|
||||||
|
$cols = 4;
|
||||||
|
$invalidID = 5; /* should trigger bad shape for construction with val */
|
||||||
|
$raggedr = 0; /* (raggedr,raggedc) should be out of bounds in ragged array */
|
||||||
|
$raggedc = 4;
|
||||||
|
$validID = 3; /* leading dimension of intended test Matrices */
|
||||||
|
$nonconformld = 4; /* leading dimension which is valid, but nonconforming */
|
||||||
|
$ib = 1; /* index ranges for sub Matrix */
|
||||||
|
$ie = 2;
|
||||||
|
$jb = 1;
|
||||||
|
$je = 3;
|
||||||
|
$rowindexset = array(1,2);
|
||||||
|
$badrowindexset = array(1,3);
|
||||||
|
$columnindexset = array(1,2,3);
|
||||||
|
$badcolumnindexset = array(1,2,4);
|
||||||
|
$columnsummax = 33.;
|
||||||
|
$rowsummax = 30.;
|
||||||
|
$sumofdiagonals = 15;
|
||||||
|
$sumofsquares = 650;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test matrix methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructors and constructor-like methods:
|
||||||
|
*
|
||||||
|
* Matrix(double[], int)
|
||||||
|
* Matrix(double[][])
|
||||||
|
* Matrix(int, int)
|
||||||
|
* Matrix(int, int, double)
|
||||||
|
* Matrix(int, int, double[][])
|
||||||
|
* constructWithCopy(double[][])
|
||||||
|
* random(int,int)
|
||||||
|
* identity(int)
|
||||||
|
*/
|
||||||
|
echo "<p>Testing constructors and constructor-like methods...</p>";
|
||||||
|
|
||||||
|
$A = new Matrix($columnwise, 3);
|
||||||
|
if($A instanceof Matrix) {
|
||||||
|
$this->try_success("Column-packed constructor...");
|
||||||
|
} else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "Column-packed constructor...", "Unable to construct Matrix");
|
||||||
|
|
||||||
|
$T = new Matrix($tvals);
|
||||||
|
if($T instanceof Matrix)
|
||||||
|
$this->try_success("2D array constructor...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "2D array constructor...", "Unable to construct Matrix");
|
||||||
|
|
||||||
|
$A = new Matrix($columnwise, $validID);
|
||||||
|
$B = new Matrix($avals);
|
||||||
|
$tmp = $B->get(0,0);
|
||||||
|
$avals[0][0] = 0.0;
|
||||||
|
$C = $B->minus($A);
|
||||||
|
$avals[0][0] = $tmp;
|
||||||
|
$B = Matrix::constructWithCopy($avals);
|
||||||
|
$tmp = $B->get(0,0);
|
||||||
|
$avals[0][0] = 0.0;
|
||||||
|
/** check that constructWithCopy behaves properly **/
|
||||||
|
if ( ( $tmp - $B->get(0,0) ) != 0.0 )
|
||||||
|
$errorCount = $this->try_failure($errorCount,"constructWithCopy... ","copy not effected... data visible outside");
|
||||||
|
else
|
||||||
|
$this->try_success("constructWithCopy... ","");
|
||||||
|
|
||||||
|
$I = new Matrix($ivals);
|
||||||
|
if ( $this->checkMatrices($I,Matrix::identity(3,4)) )
|
||||||
|
$this->try_success("identity... ","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"identity... ","identity Matrix not successfully created");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access Methods:
|
||||||
|
*
|
||||||
|
* getColumnDimension()
|
||||||
|
* getRowDimension()
|
||||||
|
* getArray()
|
||||||
|
* getArrayCopy()
|
||||||
|
* getColumnPackedCopy()
|
||||||
|
* getRowPackedCopy()
|
||||||
|
* get(int,int)
|
||||||
|
* getMatrix(int,int,int,int)
|
||||||
|
* getMatrix(int,int,int[])
|
||||||
|
* getMatrix(int[],int,int)
|
||||||
|
* getMatrix(int[],int[])
|
||||||
|
* set(int,int,double)
|
||||||
|
* setMatrix(int,int,int,int,Matrix)
|
||||||
|
* setMatrix(int,int,int[],Matrix)
|
||||||
|
* setMatrix(int[],int,int,Matrix)
|
||||||
|
* setMatrix(int[],int[],Matrix)
|
||||||
|
*/
|
||||||
|
print "<p>Testing access methods...</p>";
|
||||||
|
|
||||||
|
$B = new Matrix($avals);
|
||||||
|
if($B->getRowDimension() == $rows)
|
||||||
|
$this->try_success("getRowDimension...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "getRowDimension...");
|
||||||
|
|
||||||
|
if($B->getColumnDimension() == $cols)
|
||||||
|
$this->try_success("getColumnDimension...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "getColumnDimension...");
|
||||||
|
|
||||||
|
$barray = $B->getArray();
|
||||||
|
if($this->checkArrays($barray, $avals))
|
||||||
|
$this->try_success("getArray...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "getArray...");
|
||||||
|
|
||||||
|
$bpacked = $B->getColumnPackedCopy();
|
||||||
|
if($this->checkArrays($bpacked, $columnwise))
|
||||||
|
$this->try_success("getColumnPackedCopy...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "getColumnPackedCopy...");
|
||||||
|
|
||||||
|
$bpacked = $B->getRowPackedCopy();
|
||||||
|
if($this->checkArrays($bpacked, $rowwise))
|
||||||
|
$this->try_success("getRowPackedCopy...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "getRowPackedCopy...");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array-like methods:
|
||||||
|
* minus
|
||||||
|
* minusEquals
|
||||||
|
* plus
|
||||||
|
* plusEquals
|
||||||
|
* arrayLeftDivide
|
||||||
|
* arrayLeftDivideEquals
|
||||||
|
* arrayRightDivide
|
||||||
|
* arrayRightDivideEquals
|
||||||
|
* arrayTimes
|
||||||
|
* arrayTimesEquals
|
||||||
|
* uminus
|
||||||
|
*/
|
||||||
|
print "<p>Testing array-like methods...</p>";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I/O methods:
|
||||||
|
* read
|
||||||
|
* print
|
||||||
|
* serializable:
|
||||||
|
* writeObject
|
||||||
|
* readObject
|
||||||
|
*/
|
||||||
|
print "<p>Testing I/O methods...</p>";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test linear algebra methods
|
||||||
|
*/
|
||||||
|
echo "<p>Testing linear algebra methods...<p>";
|
||||||
|
|
||||||
|
$A = new Matrix($columnwise, 3);
|
||||||
|
if( $this->checkMatrices($A->transpose(), $T) )
|
||||||
|
$this->try_success("Transpose check...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "Transpose check...", "Matrices are not equal");
|
||||||
|
|
||||||
|
if($this->checkScalars($A->norm1(), $columnsummax))
|
||||||
|
$this->try_success("Maximum column sum...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "Maximum column sum...", "Incorrect: " . $A->norm1() . " != " . $columnsummax);
|
||||||
|
|
||||||
|
if($this->checkScalars($A->normInf(), $rowsummax))
|
||||||
|
$this->try_success("Maximum row sum...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "Maximum row sum...", "Incorrect: " . $A->normInf() . " != " . $rowsummax );
|
||||||
|
|
||||||
|
if($this->checkScalars($A->normF(), sqrt($sumofsquares)))
|
||||||
|
$this->try_success("Frobenius norm...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "Frobenius norm...", "Incorrect:" . $A->normF() . " != " . sqrt($sumofsquares));
|
||||||
|
|
||||||
|
if($this->checkScalars($A->trace(), $sumofdiagonals))
|
||||||
|
$this->try_success("Matrix trace...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "Matrix trace...", "Incorrect: " . $A->trace() . " != " . $sumofdiagonals);
|
||||||
|
|
||||||
|
$B = $A->getMatrix(0, $A->getRowDimension(), 0, $A->getRowDimension());
|
||||||
|
if( $B->det() == 0 )
|
||||||
|
$this->try_success("Matrix determinant...");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "Matrix determinant...", "Incorrect: " . $B->det() . " != " . 0);
|
||||||
|
|
||||||
|
$A = new Matrix($columnwise,3);
|
||||||
|
$SQ = new Matrix($square);
|
||||||
|
if ($this->checkMatrices($SQ, $A->times($A->transpose())))
|
||||||
|
$this->try_success("times(Matrix)...");
|
||||||
|
else {
|
||||||
|
$errorCount = $this->try_failure($errorCount, "times(Matrix)...", "Unable to multiply matrices");
|
||||||
|
$SQ->toHTML();
|
||||||
|
$AT->toHTML();
|
||||||
|
}
|
||||||
|
|
||||||
|
$A = new Matrix($columnwise, 4);
|
||||||
|
|
||||||
|
$QR = $A->qr();
|
||||||
|
$R = $QR->getR();
|
||||||
|
$Q = $QR->getQ();
|
||||||
|
if($this->checkMatrices($A, $Q->times($R)))
|
||||||
|
$this->try_success("QRDecomposition...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"QRDecomposition...","incorrect qr decomposition calculation");
|
||||||
|
|
||||||
|
$A = new Matrix($columnwise, 4);
|
||||||
|
$SVD = $A->svd();
|
||||||
|
$U = $SVD->getU();
|
||||||
|
$S = $SVD->getS();
|
||||||
|
$V = $SVD->getV();
|
||||||
|
if ($this->checkMatrices($A, $U->times($S->times($V->transpose()))))
|
||||||
|
$this->try_success("SingularValueDecomposition...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"SingularValueDecomposition...","incorrect singular value decomposition calculation");
|
||||||
|
|
||||||
|
$n = $A->getColumnDimension();
|
||||||
|
$A = $A->getMatrix(0,$n-1,0,$n-1);
|
||||||
|
$A->set(0,0,0.);
|
||||||
|
|
||||||
|
$LU = $A->lu();
|
||||||
|
$L = $LU->getL();
|
||||||
|
if ( $this->checkMatrices($A->getMatrix($LU->getPivot(),0,$n-1), $L->times($LU->getU())) )
|
||||||
|
$this->try_success("LUDecomposition...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"LUDecomposition...","incorrect LU decomposition calculation");
|
||||||
|
|
||||||
|
$X = $A->inverse();
|
||||||
|
if ( $this->checkMatrices($A->times($X),Matrix::identity(3,3)) )
|
||||||
|
$this->try_success("inverse()...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount, "inverse()...","incorrect inverse calculation");
|
||||||
|
|
||||||
|
$DEF = new Matrix($rankdef);
|
||||||
|
if($this->checkScalars($DEF->rank(), min($DEF->getRowDimension(), $DEF->getColumnDimension())-1))
|
||||||
|
$this->try_success("Rank...");
|
||||||
|
else
|
||||||
|
$this->try_failure("Rank...", "incorrect rank calculation");
|
||||||
|
|
||||||
|
$B = new Matrix($condmat);
|
||||||
|
$SVD = $B->svd();
|
||||||
|
$singularvalues = $SVD->getSingularValues();
|
||||||
|
if($this->checkScalars($B->cond(), $singularvalues[0]/$singularvalues[min($B->getRowDimension(), $B->getColumnDimension())-1]))
|
||||||
|
$this->try_success("Condition number...");
|
||||||
|
else
|
||||||
|
$this->try_failure("Condition number...", "incorrect condition number calculation");
|
||||||
|
|
||||||
|
$SUB = new Matrix($subavals);
|
||||||
|
$O = new Matrix($SUB->getRowDimension(),1,1.0);
|
||||||
|
$SOL = new Matrix($sqSolution);
|
||||||
|
$SQ = $SUB->getMatrix(0,$SUB->getRowDimension()-1,0,$SUB->getRowDimension()-1);
|
||||||
|
if ( $this->checkMatrices($SQ->solve($SOL),$O) )
|
||||||
|
$this->try_success("solve()...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"solve()...","incorrect lu solve calculation");
|
||||||
|
|
||||||
|
$A = new Matrix($pvals);
|
||||||
|
$Chol = $A->chol();
|
||||||
|
$L = $Chol->getL();
|
||||||
|
if ( $this->checkMatrices($A, $L->times($L->transpose())) )
|
||||||
|
$this->try_success("CholeskyDecomposition...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"CholeskyDecomposition...","incorrect Cholesky decomposition calculation");
|
||||||
|
|
||||||
|
$X = $Chol->solve(Matrix::identity(3,3));
|
||||||
|
if ( $this->checkMatrices($A->times($X), Matrix::identity(3,3)) )
|
||||||
|
$this->try_success("CholeskyDecomposition solve()...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"CholeskyDecomposition solve()...","incorrect Choleskydecomposition solve calculation");
|
||||||
|
|
||||||
|
$Eig = $A->eig();
|
||||||
|
$D = $Eig->getD();
|
||||||
|
$V = $Eig->getV();
|
||||||
|
if( $this->checkMatrices($A->times($V),$V->times($D)) )
|
||||||
|
$this->try_success("EigenvalueDecomposition (symmetric)...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (symmetric)...","incorrect symmetric Eigenvalue decomposition calculation");
|
||||||
|
|
||||||
|
$A = new Matrix($evals);
|
||||||
|
$Eig = $A->eig();
|
||||||
|
$D = $Eig->getD();
|
||||||
|
$V = $Eig->getV();
|
||||||
|
if ( $this->checkMatrices($A->times($V),$V->times($D)) )
|
||||||
|
$this->try_success("EigenvalueDecomposition (nonsymmetric)...","");
|
||||||
|
else
|
||||||
|
$errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (nonsymmetric)...","incorrect nonsymmetric Eigenvalue decomposition calculation");
|
||||||
|
|
||||||
|
print("<b>{$errorCount} total errors</b>.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print appropriate messages for successful outcome try
|
||||||
|
* @param string $s
|
||||||
|
* @param string $e
|
||||||
|
*/
|
||||||
|
function try_success($s, $e = "") {
|
||||||
|
print "> ". $s ."success<br />";
|
||||||
|
if ($e != "")
|
||||||
|
print "> Message: ". $e ."<br />";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print appropriate messages for unsuccessful outcome try
|
||||||
|
* @param int $count
|
||||||
|
* @param string $s
|
||||||
|
* @param string $e
|
||||||
|
* @return int incremented counter
|
||||||
|
*/
|
||||||
|
function try_failure($count, $s, $e="") {
|
||||||
|
print "> ". $s ."*** failure ***<br />> Message: ". $e ."<br />";
|
||||||
|
return ++$count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print appropriate messages for unsuccessful outcome try
|
||||||
|
* @param int $count
|
||||||
|
* @param string $s
|
||||||
|
* @param string $e
|
||||||
|
* @return int incremented counter
|
||||||
|
*/
|
||||||
|
function try_warning($count, $s, $e="") {
|
||||||
|
print "> ". $s ."*** warning ***<br />> Message: ". $e ."<br />";
|
||||||
|
return ++$count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check magnitude of difference of "scalars".
|
||||||
|
* @param float $x
|
||||||
|
* @param float $y
|
||||||
|
*/
|
||||||
|
function checkScalars($x, $y) {
|
||||||
|
$eps = pow(2.0,-52.0);
|
||||||
|
if ($x == 0 & abs($y) < 10*$eps) return;
|
||||||
|
if ($y == 0 & abs($x) < 10*$eps) return;
|
||||||
|
if (abs($x-$y) > 10 * $eps * max(abs($x),abs($y)))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check norm of difference of "vectors".
|
||||||
|
* @param float $x[]
|
||||||
|
* @param float $y[]
|
||||||
|
*/
|
||||||
|
function checkVectors($x, $y) {
|
||||||
|
$nx = count($x);
|
||||||
|
$ny = count($y);
|
||||||
|
if ($nx == $ny)
|
||||||
|
for($i=0; $i < $nx; ++$i)
|
||||||
|
$this->checkScalars($x[$i],$y[$i]);
|
||||||
|
else
|
||||||
|
die("Attempt to compare vectors of different lengths");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check norm of difference of "arrays".
|
||||||
|
* @param float $x[][]
|
||||||
|
* @param float $y[][]
|
||||||
|
*/
|
||||||
|
function checkArrays($x, $y) {
|
||||||
|
$A = new Matrix($x);
|
||||||
|
$B = new Matrix($y);
|
||||||
|
return $this->checkMatrices($A,$B);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check norm of difference of "matrices".
|
||||||
|
* @param matrix $X
|
||||||
|
* @param matrix $Y
|
||||||
|
*/
|
||||||
|
function checkMatrices($X = null, $Y = null) {
|
||||||
|
if( $X == null || $Y == null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$eps = pow(2.0,-52.0);
|
||||||
|
if ($X->norm1() == 0. & $Y->norm1() < 10*$eps) return true;
|
||||||
|
if ($Y->norm1() == 0. & $X->norm1() < 10*$eps) return true;
|
||||||
|
|
||||||
|
$A = $X->minus($Y);
|
||||||
|
|
||||||
|
if ($A->norm1() > 1000 * $eps * max($X->norm1(),$Y->norm1()))
|
||||||
|
die("The norm of (X-Y) is too large: ".$A->norm1());
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = new TestMatrix;
|
||||||
|
?>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue