2
0
forked from Wavyzz/dolibarr

Mise a jour librairie php_writeexcel en 0.3.0 (la prcdente ne fonctionne pas en php5)

This commit is contained in:
Laurent Destailleur
2006-01-27 20:52:08 +00:00
parent c5462977e4
commit 08615d2bbc
27 changed files with 3430 additions and 1316 deletions

View File

@@ -1,3 +1,32 @@
0.3.0 (2005-11-01):
- Fixed cell merging (fix contributed by Nicolas Kahn - thanks!)
- Corrected the README: formulas are supported since version 0.2.2
- Added a method named set_codepage() to the workbook object which
allows to set the codepage (fixes German Umlauts on Macs for
example, contributed by Stefan Gr<47>nig - thanks!)
- Changed all calls of call_user_method_array() to call_user_func_array()
as recent PHP versions complain about call_user_method_array() being
deprecated (reported by Julien Detante and Luc Cessieux)
- Added $_debug to the class variable declaration of
class.writeexcel_biffwriter.inc.php and
class.writeexcel_worksheet.inc.php so that PHP doesn't complain about it
- The demos now produce proper headers ("Content-Type" and
"Content-Disposition") so that the correct application gets loaded
when an XLS file is received more reliably (thanks to
C. Mourad Jaber)
- Temporary files are now deleted (reported by Siggi Oskarsson)
- Added example-colors.php
- Fixed frozen and thawed panes (reported by Roger Jochem and Flavio
Ciotola)
- Added example-panes.php to prove that it's really fixed ;-)
- Added example-repeat.php because somebody reported that it doesn't
work - it does work for me, please report again if it fails for you
and send me your code
- Fixed cell range formulas like '$A$1:$B$2' which should now work
(thanks Cedric Chandon)
- Fixed the PHP 5 incompatibility (reported by several people, patch
by Jean Pasdeloup, thanks!)
0.2.2 (2003-10-08):
- Cleaned up class.writeexcel_biffwriter.inc.php
- Cleaned up _append() and _prepend() in class.writeexcel_biffwriter.inc.php

View File

@@ -1 +1 @@
You can contact me via email at <jonny@1409.org>.
You can contact me via email at <jonny@nurfuerspam.de>.

View File

@@ -1,18 +1,33 @@
Q: Could you please add support for XYZGJGNDF?
A: Sorry, this project is at its alpha stage. I won't add any new features
until there is a stable version.
A: Sorry, I don't have the time to make this a full-featured project.
It only contains the features which I need (and which were supported
by SpreadSheet:WriteExcel anyway). You are welcome to add features
yourself though and send it to me for inclusion.
Q: The files class.ole_pps_root.php and class.ole_pps_file.php are
missing. Where can I get them?
A: They are only required for big file (>7 MB) support and available
as a seperate project at
http://bettina-attack.de/jonny/view.php?path=/projects/php_ole/
http://bettina-attack.de/jonny/view.php/projects/php_ole/
Q: How can I create files bigger than 7 MB?
A: Use class.writeexcel_workbookbig.inc.php instead of
class.writeexcel_workbook.inc.php. You'll need the php_ole project
available at
http://bettina-attack.de/jonny/view.php?path=/projects/php_ole/
http://bettina-attack.de/jonny/view.php/projects/php_ole/
Q: Will you make the project PEAR compliant?
A: Probably. But this means a lot of work and will require some time.
Q: Is there a 'auto-column-width' function?
A: AFAIK Excel doesn't store this information in the XLS files but
calculates the auto-width at run-time, so this doesn't seem to be
possible, sorry.
Q: Is it possible to include Unicode strings in a worksheet?
A: Sorry, this is not possible due to the restrictions of the Excel 5
format which is still used.
Q: Is it possible to include strings with a length of more than
255 characters?
A: No, sorry. Please see the TODO file.

View File

@@ -1 +1 @@
http://www.bettina-attack.de/jonny/projects/php_writeexcel/
http://www.bettina-attack.de/jonny/view.php/projects/php_writeexcel/

View File

@@ -67,21 +67,20 @@ with while porting SpreadSheet::WriteExcel to PHP:
What features are currently supported?
--------------------------------------
Basically all features of Spreadsheet::WriteExcel will hopefully be
supported one day. However, it makes use of some Perl packages with
functions I did not yet find for PHP.
Basically all features of Spreadsheet::WriteExcel are supported and
thanks to a lot of people (see CHANGELOG) who contributed code and bug
fixes, most things seem to work. However, please remember that it's still
in beta stage, so there are probably some bugs left.
Spreadsheet::WriteExcel uses the Parse::RecDescent package for formula
support. I havn't looked for a Recursive Descent parser for PHP yet. Thus
Excel formulas are not yet supported.
support. Andreas Brodowski has imported and changed the PEAR::Spreadsheet
Parser.php file, so formulas are supported since version 0.2.2.
Spreadsheet::WriteExcel uses the OLE::Storage_Lite package for
supporting Excel files bigger than approx. 7 MB. I have ported this
package already and called it php_ole. But I really don't know how
reliable it is, so use it with care!
All other features SHOULD work.
Documentation

View File

@@ -0,0 +1,9 @@
The maximum string length is 255 due to the Excel 5 format which is
still used. The long_string.pl example coming with
SpreadSheet::WriteExcel does not work for some reason. It must be
figured out why.
Volker Sauer has reported that sheet names in Excel files generated by
php_writeexcel get prepended with ".xls]" when he renames them, but I
can't reproduce it. If you can, please send me the generated file and
the version number of Excel you are using.

View File

@@ -0,0 +1,541 @@
<?php
/*
* Copyleft 2002 Johann Hanne
*
* This 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 software 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 software; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This is the OLE::Storage_Lite Perl package ported to PHP
* OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
*/
require_once "functions.ole.php";
class ole {
var $sFile;
#------------------------------------------------------------------------------
# new OLE::Storage_Lite
#------------------------------------------------------------------------------
function ole($sFile) {
$this->sFile=$sFile;
}
#------------------------------------------------------------------------------
# getPpsTree: OLE::Storage_Lite
#------------------------------------------------------------------------------
function getPpsTree($bData=false) {
#0.Init
$rhInfo = _initParse($this->_FILE);
if (!$rhInfo) {
return false;
}
#1. Get Data
list($oPps) = _getPpsTree(0, $rhInfo, $bData);
// close(IN);
return $oPps;
}
#------------------------------------------------------------------------------
# getSearch: OLE::Storage_Lite
#------------------------------------------------------------------------------
function getPpsSearch($raName, $bData=false, $iCase=false) {
#0.Init
$rhInfo = _initParse($this->_FILE);
if (!$rhInfo) {
return false;
}
#1. Get Data
$aList = _getPpsSearch(0, $rhInfo, $raName, $bData, $iCase);
// close(IN);
return $aList;
}
#------------------------------------------------------------------------------
# getNthPps: OLE::Storage_Lite
#------------------------------------------------------------------------------
function getNthPps($iNo, $bData=false) {
#0.Init
$rhInfo = _initParse($this->_FILE);
if (!$rhInfo) {
return false;
}
#1. Get Data
$oPps = _getNthPps($iNo, $rhInfo, $bData);
// close IN;
return $oPps;
}
#------------------------------------------------------------------------------
# _initParse: OLE::Storage_Lite
#------------------------------------------------------------------------------
function _initParse($sFile) {
//$oIo;
#1. $sFile is a resource (hopefully a file resource)
if (is_resource($sFile)) {
$oIo=$sFile;
}
#2. $sFile is a filename string
else {
$oIo=fopen($sFile, "rb");
}
return _getHeaderInfo($oIo);
}
#------------------------------------------------------------------------------
# _getPpsTree: OLE::Storage_Lite
#------------------------------------------------------------------------------
function _getPpsTree($iNo, $rhInfo, $bData, &$raDone) { // last par optional!
if($raDone!==false) {
if(in_array($iNo, $raDone)) {
return array();
}
} else {
$raDone=array();
}
array_push($raDone, $iNo);
$iRootBlock = $rhInfo->_ROOT_START;
#1. Get Information about itself
$oPps = _getNthPps($iNo, $rhInfo, $bData);
#2. Child
if($oPps->DirPps != 0xFFFFFFFF) {
$aChildL = _getPpsTree($oPps->DirPps, $rhInfo, $bData, $raDone);
$oPps->Child =& $aChildL;
} else {
$oPps->Child = false;
}
#3. Previous,Next PPSs
$aList = array();
if ($oPps->PrevPps != 0xFFFFFFFF) {
array_push($aList, _getPpsTree($oPps->PrevPps, $rhInfo, $bData, $raDone));
}
array_push($aList, $oPps);
if ($oPps->NextPps != 0xFFFFFFFF) {
array_push($aList, _getPpsTree($oPps->NextPps, $rhInfo, $bData, $raDone));
}
return $aList;
}
#------------------------------------------------------------------------------
# _getPpsSearch: OLE::Storage_Lite
#------------------------------------------------------------------------------
function _getPpsSearch($iNo, $rhInfo, $raName, $bData, $iCase, &$raDone) { // last par optional!
$iRootBlock = $rhInfo->_ROOT_START;
//my @aRes;
#1. Check it self
if($raDone!==false) {
if(in_array($iNo, $raDone)) {
return array();
}
} else {
$raDone=array();
}
array_push($raDone, $iNo);
$oPps = _getNthPps($iNo, $rhInfo, false);
$found=false;
foreach ($raName as $cmp) {
if (($iCase && strcasecmp($oPps->Name, $cmp)==0) ||
strcmp($oPps->Name, $cmp)==0) {
$found=true;
break;
}
}
if ($found) {
if ($bData) {
$oPps = _getNthPps($iNo, $rhInfo, $bData);
}
$aRes = array($oPps);
} else {
$aRes = array();
}
#2. Check Child, Previous, Next PPSs
if ($oPps->DirPps != 0xFFFFFFFF) {
array_push($aRes, _getPpsSearch($oPps->DirPps, $rhInfo, $raName, $bData, $iCase, $raDone));
}
if ($oPps->PrevPps != 0xFFFFFFFF) {
array_push($aRes, _getPpsSearch($oPps->PrevPps, $rhInfo, $raName, $bData, $iCase, $raDone));
}
if ($oPps->NextPps != 0xFFFFFFFF) {
array_push($aRes, _getPpsSearch($oPps->NextPps, $rhInfo, $raName, $bData, $iCase, $raDone));
}
return $aRes;
}
#===================================================================
# Get Header Info (BASE Informain about that file)
#===================================================================
function _getHeaderInfo($FILE) {
//my($iWk);
$rhInfo = new object();
$rhInfo->_FILEH_ = $FILE;
//my $sWk;
#0. Check ID
fseek($rhInfo->_FILEH_, 0, SEEK_SET);
$sWk=fread($rhInfo->_FILEH_, 8);
if ($sWk!="\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1") {
return false;
}
#BIG BLOCK SIZE
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x1E, 2, "v");
if ($iWk===false) {
return false;
}
$rhInfo->_BIG_BLOCK_SIZE = pow(2, $iWk);
#SMALL BLOCK SIZE
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x20, 2, "v");
if ($iWk===false) {
return false;
}
$rhInfo->_SMALL_BLOCK_SIZE = pow(2, $iWk);
#BDB Count
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x2C, 4, "V");
if ($iWk===false) {
return false;
}
$rhInfo->_BDB_COUNT = $iWk;
#START BLOCK
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x30, 4, "V");
if ($iWk===false) {
return false;
}
$rhInfo->_ROOT_START = $iWk;
#MIN SIZE OF BB
# $iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x38, 4, "V");
# if ($iWk===false) {
# return false;
# }
# $rhInfo->_MIN_SIZE_BB = $iWk;
#SMALL BD START
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x3C, 4, "V");
if ($iWk===false) {
return false;
}
$rhInfo->_SBD_START = $iWk;
#SMALL BD COUNT
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x40, 4, "V");
if ($iWk===false) {
return false;
}
$rhInfo->_SBD_COUNT = $iWk;
#EXTRA BBD START
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x44, 4, "V");
if ($iWk===false) {
return false;
}
$rhInfo->_EXTRA_BBD_START = $iWk;
#EXTRA BD COUNT
$iWk = _getInfoFromFile($rhInfo->_FILEH_, 0x48, 4, "V");
if ($iWk===false) {
return false;
}
$rhInfo->_EXTRA_BBD_COUNT = $iWk;
#GET BBD INFO
$rhInfo->_BBD_INFO= _getBbdInfo($rhInfo);
#GET ROOT PPS
$oRoot = _getNthPps(0, $rhInfo, false);
$rhInfo->_SB_START = $oRoot->StartBlock;
$rhInfo->_SB_SIZE = $oRoot->Size;
return $rhInfo;
}
#------------------------------------------------------------------------------
# _getInfoFromFile
#------------------------------------------------------------------------------
function _getInfoFromFile($FILE, $iPos, $iLen, $sFmt) {
//my($sWk);
if (!$FILE) {
return false;
}
if (fseek($FILE, $iPos, SEEK_SET)!==0) {
return false;
}
$sWk=fread($FILE, $iLen);
$data=unpack($sFmt."ret", $sWk);
return $data["ret"];
}
#------------------------------------------------------------------------------
# _getBbdInfo
#------------------------------------------------------------------------------
function _getBbdInfo($rhInfo) {
$aBdList = array();
$iBdbCnt = $rhInfo->_BDB_COUNT;
//my $iGetCnt;
//my $sWk;
$i1stCnt = floor(($rhInfo->_BIG_BLOCK_SIZE - 0x4C) / LongIntSize);
$iBdlCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize) - 1;
#1. 1st BDlist
fseek ($rhInfo->_FILEH_, 0x4C, SEEK_SET);
$iGetCnt = ($iBdbCnt < $i1stCnt) ? $iBdbCnt : $i1stCnt;
$sWk=fread($rhInfo->_FILEH_, LongIntSize*$iGetCnt);
$data=unpack("V".$iGetCnt."int", $sWk);
for ($c=0;$c<$iGetCnt;$c++) {
array_push ($aBdList, $data["int$c"]);
}
$iBdbCnt -= $iGetCnt;
#2. Extra BDList
$iBlock = $rhInfo->_EXTRA_BBD_START;
while(($iBdbCnt> 0) && _isNormalBlock($iBlock)){
_setFilePos($iBlock, 0, $rhInfo);
$iGetCnt= ($iBdbCnt < $iBdlCnt) ? $iBdbCnt : $iBdlCnt;
$sWk=fread($rhInfo->_FILEH_, LongIntSize*$iGetCnt);
$data=unpack("V".$iGetCnt."int", $sWk);
for ($c=0;$c<$iGetCnt;$c++) {
array_push ($aBdList, $data["int$c"]);
}
$iBdbCnt -= $iGetCnt;
$sWk=fread($rhInfo->_FILEH_, LongIntSize);
$data=unpack("Vint", $sWk);
$iBlock = $data["int"];
}
#3.Get BDs
$aWk=array();
$hBd=array();
$iBlkNo = 0;
//my $iBdL;
//my $i;
$iBdCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize);
foreach ($aBdList as $iBdl) {
// foreach $iBdL (@aBdList) {
_setFilePos($iBdL, 0, $rhInfo);
$sWk=fread($rhInfo->_FILEH_, $rhInfo->_BIG_BLOCK_SIZE);
$aWk = unpack("V".$iBdCnt."int", $sWk);
for ($i=0;$i<$iBdCnt;$i++, $iBlkNo++) {
if($aWk["int".$i] != ($iBlkNo+1)) {
$hBd["$iBlkNo"] = $aWk["int".$i];
}
}
}
return $hBd;
}
#------------------------------------------------------------------------------
# getNthPps (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _getNthPps($iPos, $rhInfo, $bData) {
$iPpsStart = $rhInfo->_ROOT_START;
//my($iPpsBlock, $iPpsPos);
//my $sWk;
//my $iBlock;
$iBaseCnt = $rhInfo->_BIG_BLOCK_SIZE / PpsSize;
$iPpsBlock = floor($iPos / $iBaseCnt);
$iPpsPos = $iPos % $iBaseCnt;
$iBlock = _getNthBlockNo($iPpsStart, $iPpsBlock, $rhInfo);
if ($iBlock===false) {
return false;
}
_setFilePos($iBlock, PpsSize*$iPpsPos, $rhInfo);
$sWk=fread($rhInfo->_FILEH_, PpsSize);
// return undef unless($sWk);
//TODO: substr() binary safe?
$data=unpack("vint", substr($sWk, 0x40, 2));
$iNmSize = $data["int"];
$iNmSize = ($iNmSize > 2) ? $iNmSize - 2 : $iNmSize;
$sNm= substr($sWk, 0, $iNmSize);
$data=unpack("Cint", substr($sWk, 0x42, 2));
$iType = $data["int"];
$data=unpack("V3int", substr($sWk, 0x44, LongIntSize*3));
$lPpsPrev = $data["int1"];
$lPpsNext = $data["int2"];
$lDirPps = $data["int3"];
// TODO: Original lines terminated by commas: ?!
/*
my @raTime1st =
(($iType == PpsType_Root) or ($iType == PpsType_Dir))?
OLEDate2Local(substr($sWk, 0x64, 8)) : undef ,
my @raTime2nd =
(($iType == PpsType_Root) or ($iType == PpsType_Dir))?
OLEDate2Local(substr($sWk, 0x6C, 8)) : undef,
*/
$raTime1st = (($iType == PpsType_Root) or ($iType == PpsType_Dir)) ?
OLEDate2Local(substr($sWk, 0x64, 8)) : false;
$raTime2nd = (($iType == PpsType_Root) or ($iType == PpsType_Dir)) ?
OLEDate2Local(substr($sWk, 0x6C, 8)) : false;
$data=unpack("V2int", substr($sWk, 0x74, 8));
$iStart=$data["int1"];
$iSize=$data["int2"];
if ($bData) {
$sData = _getData($iType, $iStart, $iSize, $rhInfo);
/* TODO!!!
return OLE::Storage_Lite::PPS->new(
$iPos, $sNm, $iType, $lPpsPrev, $lPpsNext, $lDirPps,
\@raTime1st, \@raTime2nd, $iStart, $iSize, $sData, undef);
*/
} else {
/* TODO!!!
return OLE::Storage_Lite::PPS->new(
$iPos, $sNm, $iType, $lPpsPrev, $lPpsNext, $lDirPps,
\@raTime1st, \@raTime2nd, $iStart, $iSize, undef, undef);
*/
}
}
#------------------------------------------------------------------------------
# _setFilePos (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _setFilePos($iBlock, $iPos, $rhInfo) {
fseek($rhInfo->_FILEH_, ($iBlock+1)*$rhInfo->_BIG_BLOCK_SIZE+$iPos,
SEEK_SET);
}
#------------------------------------------------------------------------------
# _getNthBlockNo (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _getNthBlockNo($iStBlock, $iNth, $rhInfo) {
//my $iSv;
$iNext = $iStBlock;
for ($i=0; $i<$iNth; $i++) {
$iSv = $iNext;
$iNext = _getNextBlockNo($iSv, $rhInfo);
if (!_isNormalBlock($iNext)) {
return;
}
}
return $iNext;
}
#------------------------------------------------------------------------------
# _getData (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _getData($iType, $iBlock, $iSize, $rhInfo) {
if ($iType == PpsType_File) {
if($iSize < DataSizeSmall) {
return _getSmallData($iBlock, $iSize, $rhInfo);
} else {
return _getBigData($iBlock, $iSize, $rhInfo);
}
} elseif($iType == PpsType_Root) { #Root
return _getBigData($iBlock, $iSize, $rhInfo);
} elseif($iType == PpsType_Dir) { # Directory
return false;
}
}
#------------------------------------------------------------------------------
# _getBigData (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _getBigData($iBlock, $iSize, $rhInfo) {
//my($iRest, $sWk, $sRes);
if (!_isNormalBlock($iBlock)) {
return '';
}
$iRest = $iSize;
//my($i, $iGetSize, $iNext);
$sRes = '';
/* TODO
my @aKeys= sort({$a<=>$b} keys(%{$rhInfo->{_BBD_INFO}}));
while ($iRest > 0) {
my @aRes = grep($_ >= $iBlock, @aKeys);
my $iNKey = $aRes[0];
$i = $iNKey - $iBlock;
$iNext = $rhInfo->{_BBD_INFO}{$iNKey};
_setFilePos($iBlock, 0, $rhInfo);
my $iGetSize = ($rhInfo->{_BIG_BLOCK_SIZE} * ($i+1));
$iGetSize = $iRest if($iRest < $iGetSize);
$rhInfo->{_FILEH_}->read( $sWk, $iGetSize);
$sRes .= $sWk;
$iRest -= $iGetSize;
$iBlock= $iNext;
}
*/
return $sRes;
}
#------------------------------------------------------------------------------
# _getNextBlockNo (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _getNextBlockNo($iBlockNo, $rhInfo) {
$iRes = $rhInfo->_BBD_INFO[$iBlockNo];
return ($iRes!==false) ? $iRes : $iBlockNo+1;
}
#------------------------------------------------------------------------------
# _isNormalBlock (OLE::Storage_Lite)
# 0xFFFFFFFC : BDList, 0xFFFFFFFD : BBD,
# 0xFFFFFFFE: End of Chain 0xFFFFFFFF : unused
#------------------------------------------------------------------------------
function _isNormalBlock($iBlock) {
return ($iBlock < 0xFFFFFFFC) ? 1 : false;
}
#------------------------------------------------------------------------------
# _getSmallData (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _getSmallData($iSmBlock, $iSize, $rhInfo) {
//my($sRes, $sWk);
$iRest = $iSize;
$sRes = '';
while ($iRest > 0) {
_setFilePosSmall($iSmBlock, $rhInfo);
$sWk=fread($rhInfo->_FILEH_, ($iRest >= $rhInfo->_SMALL_BLOCK_SIZE) ?
$rhInfo->_SMALL_BLOCK_SIZE : $iRest);
$sRes .= $sWk;
$iRest -= $rhInfo->_SMALL_BLOCK_SIZE;
$iSmBlock= _getNextSmallBlockNo($iSmBlock, $rhInfo);
}
return $sRes;
}
#------------------------------------------------------------------------------
# _setFilePosSmall(OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _setFilePosSmall($iSmBlock, $rhInfo) {
$iSmStart = $rhInfo->_SB_START;
$iBaseCnt = $rhInfo->_BIG_BLOCK_SIZE / $rhInfo->_SMALL_BLOCK_SIZE;
$iNth = floor($iSmBlock/$iBaseCnt);
$iPos = $iSmBlock % $iBaseCnt;
$iBlk = _getNthBlockNo($iSmStart, $iNth, $rhInfo);
_setFilePos($iBlk, $iPos * $rhInfo->_SMALL_BLOCK_SIZE, $rhInfo);
}
#------------------------------------------------------------------------------
# _getNextSmallBlockNo (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _getNextSmallBlockNo($iSmBlock, $rhInfo) {
//my($sWk);
$iBaseCnt = $rhInfo->_BIG_BLOCK_SIZE / LongIntSize;
$iNth = floor($iSmBlock/$iBaseCnt);
$iPos = $iSmBlock % $iBaseCnt;
$iBlk = _getNthBlockNo($rhInfo->_SBD_START, $iNth, $rhInfo);
_setFilePos($iBlk, $iPos * LongIntSize, $rhInfo);
$sWk=fread($rhInfo->_FILEH_, LongIntSize);
$data=unpack("Vint", $sWk);
return $data["int"];
}
}
?>

View File

@@ -0,0 +1,209 @@
<?php
/*
* Copyleft 2002 Johann Hanne
*
* This 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 software 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 software; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This is the OLE::Storage_Lite Perl package ported to PHP
* OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
*/
class ole_pps {
var $No;
var $Name;
var $Type;
var $PrevPps;
var $NextPps;
var $DirPps;
var $Time1st;
var $Time2nd;
var $StartBlock;
var $Size;
var $Data;
var $Child;
#------------------------------------------------------------------------------
# new (OLE::Storage_Lite::PPS)
#------------------------------------------------------------------------------
// TODO: Do we need this function?
/*
function ole_pps($iNo, $sNm, $iType, $iPrev, $iNext, $iDir,
$raTime1st, $raTime2nd, $iStart, $iSize,
$sData=false, $raChild=false) {
#1. Constructor for General Usage
if($iType == PpsType_File) { #FILE
return OLE::Storage_Lite::PPS::File->_new
($iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd,
$iStart, $iSize, $sData, $raChild);
}
elsif($iType == PpsType_Dir) { #DIRECTRY
return OLE::Storage_Lite::PPS::Dir->_new
($iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd,
$iStart, $iSize, $sData, $raChild);
}
elsif($iType == PpsType_Root) { #ROOT
return OLE::Storage_Lite::PPS::Root->_new
($iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd,
$iStart, $iSize, $sData, $raChild);
}
else {
die "Error PPS:$iType $sNm\n";
}
}
*/
// We probably don't need a constructor at all because
// all derived classed do their own initialization stuff
#------------------------------------------------------------------------------
# _new (OLE::Storage_Lite::PPS)
# for OLE::Storage_Lite
#------------------------------------------------------------------------------
function ole_pps($iNo, $sNm, $iType, $iPrev, $iNext, $iDir,
$raTime1st, $raTime2nd, $iStart, $iSize,
$sData=false, $raChild=false) {
#1. Constructor for OLE::Storage_Lite
$this->No = $iNo;
$this->Name = $sNm;
$this->Type = $iType;
$this->PrevPps = $iPrev;
$this->NextPps = $iNext;
$this->DirPps = $iDir;
$this->Time1st = $raTime1st;
$this->Time2nd = $raTime2nd;
$this->StartBlock = $iStart;
$this->Size = $iSize;
$this->Data = $sData;
$this->Child = $raChild;
}
#------------------------------------------------------------------------------
# _DataLen (OLE::Storage_Lite::PPS)
# Check for update
#------------------------------------------------------------------------------
function _DataLen() {
if ($this->Data===false) {
return 0;
}
if ($this->_PPS_FILE) {
return filesize($this->_PPS_FILE);
}
return strlen($this->Data);
}
#------------------------------------------------------------------------------
# _makeSmallData (OLE::Storage_Lite::PPS)
#------------------------------------------------------------------------------
function _makeSmallData(&$aList, $rhInfo) {
//my ($sRes);
$FILE = $rhInfo->_FILEH_;
$iSmBlk = 0;
for ($c=0;$c<sizeof($aList);$c++) {
$oPps=&$aList[$c];
#1. Make SBD, small data string
if ($oPps->Type==PpsType_File) {
if ($oPps->Size<=0) {
continue;
}
if($oPps->Size < $rhInfo->_SMALL_SIZE) {
$iSmbCnt = floor($oPps->Size / $rhInfo->_SMALL_BLOCK_SIZE) +
(($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE) ? 1 : 0);
#1.1 Add to SBD
for ($i = 0; $i<($iSmbCnt-1); $i++) {
fputs($FILE, pack("V", $i+$iSmBlk+1));
}
fputs($FILE, pack("V", -2));
#1.2 Add to Data String(this will be written for RootEntry)
#Check for update
if ($oPps->_PPS_FILE) {
//my $sBuff;
fseek($oPps->_PPS_FILE, 0, SEEK_SET); #To The Top
while ($sBuff=fread($oPps->_PPS_FILE, 4096)) {
$sRes .= $sBuff;
}
} else {
$sRes .= $oPps->Data;
}
if($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE) {
$sRes .= (str_repeat("\x00",
($rhInfo->_SMALL_BLOCK_SIZE -
($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE))));
}
#1.3 Set for PPS
$oPps->StartBlock = $iSmBlk;
$iSmBlk += $iSmbCnt;
}
}
}
$iSbCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize);
if ($iSmBlk % $iSbCnt) {
fputs($FILE, str_repeat(pack("V", -1), $iSbCnt - ($iSmBlk % $iSbCnt)));
}
#2. Write SBD with adjusting length for block
return $sRes;
}
#------------------------------------------------------------------------------
# _savePpsWk (OLE::Storage_Lite::PPS)
#------------------------------------------------------------------------------
function _savePpsWk($rhInfo) {
#1. Write PPS
$FILE=$rhInfo->_FILEH_;
fputs($FILE,
$this->Name.
str_repeat("\x00", 64 - strlen($this->Name)). # 64
pack("v", strlen($this->Name) + 2). # 66
pack("c", $this->Type). # 67
pack("c", 0x00). #UK # 68
pack("V", $this->PrevPps). #Prev # 72
pack("V", $this->NextPps). #Next # 76
pack("V", $this->DirPps). #Dir # 80
"\x00\x09\x02\x00". # 84
"\x00\x00\x00\x00". # 88
"\xc0\x00\x00\x00". # 92
"\x00\x00\x00\x46". # 96
"\x00\x00\x00\x00". # 100
//TODO!!! LocalDate2OLE($this->Time1st). # 108
"\x00\x00\x00\x00\x00\x00\x00\x00".
//TODO!!! LocalDate2OLE($this->Time2nd). # 116
"\x00\x00\x00\x00\x00\x00\x00\x00".
pack("V", ($this->StartBlock!==false) ?
$this->StartBlock : 0). # 120
pack("V", ($this->Size!==false) ?
$this->Size : 0). # 124
pack("V", 0) # 128
);
}
}
?>

View File

@@ -0,0 +1,50 @@
<?php
/*
* Copyleft 2002 Johann Hanne
*
* This 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 software 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 software; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This is the OLE::Storage_Lite Perl package ported to PHP
* OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
*/
require_once "class.ole_pps.php";
require_once "functions.ole.php";
class ole_pps_dir extends ole_pps {
function ole_pps_dir($sName, $raTime1st=false, $raTime2nd=false,
$raChild=false) {
$this->No = false;
$this->Name = $sName;
$this->Type = PpsType_Dir;
$this->PrevPps = false;
$this->NextPps = false;
$this->DirPps = false;
$this->Time1st = $raTime1st;
$this->Time2nd = $raTime2nd;
$this->StartBlock = false;
$this->Size = false;
$this->Data = false;
$this->Child = $raChild;
}
}
?>

View File

@@ -0,0 +1,74 @@
<?php
/*
* Copyleft 2002 Johann Hanne
*
* This 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 software 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 software; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This is the OLE::Storage_Lite Perl package ported to PHP
* OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
*/
require_once "class.ole_pps.php";
require_once "functions.ole.php";
class ole_pps_file extends ole_pps {
function ole_pps_file($sNm, $sData=false, $sFile=false) {
$this->No = false;
$this->Name = $sNm;
$this->Type = PpsType_File;
$this->PrevPps = false;
$this->NextPps = false;
$this->DirPps = false;
$this->Time1st = false;
$this->Time2nd = false;
$this->StartBlock = false;
$this->Size = false;
$this->Data = ($sFile===false) ? $sData : '';
$this->Child = false;
if ($sFile!==false) {
if (is_ressource($sFile)) {
$this->_PPS_FILE=$sFile;
} elseif ($sFile=="") {
$fname=tempnam("php_ole");
$this->_PPS_FILE=fopen($fname, "r+b");
} else {
$fname=$sFile;
$this->_PPS_FILE=fopen($fname, "r+b");
}
if ($sData!==false) {
fputs($this->_PPS_FILE, $sData);
}
}
}
function append ($sData) {
if ($this->_PPS_FILE) {
fputs($this->_PPS_FILE, $sData);
} else {
$this->Data.=$sData;
}
}
}
?>

View File

@@ -0,0 +1,517 @@
<?php
/*
* Copyleft 2002 Johann Hanne
*
* This 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 software 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 software; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This is the OLE::Storage_Lite Perl package ported to PHP
* OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org
*/
require_once "class.ole_pps.php";
require_once "functions.ole.php";
class ole_pps_root extends ole_pps {
function ole_pps_root($raTime1st=false, $raTime2nd=false, $raChild=false) {
$this->No = false;
$this->Name = Asc2Ucs('Root Entry');
$this->Type = PpsType_Root;
$this->PrevPps = false;
$this->NextPps = false;
$this->DirPps = false;
$this->Time1st = $raTime1st;
$this->Time2nd = $raTime2nd;
$this->StartBlock = false;
$this->Size = false;
$this->Data = false;
$this->Child = $raChild;
}
#------------------------------------------------------------------------------
# save (OLE::Storage_Lite::PPS::Root)
#------------------------------------------------------------------------------
function save($sFile, $bNoAs=false, $rhInfo=false) {
#0.Initial Setting for saving
/*
if (!$rhInfo) {
$rhInfo=new object();
}
*/
$rhInfo->_BIG_BLOCK_SIZE=pow(2, (($rhInfo->_BIG_BLOCK_SIZE) ?
_adjust2($rhInfo->_BIG_BLOCK_SIZE) : 9));
$rhInfo->_SMALL_BLOCK_SIZE=pow(2, (($rhInfo->_SMALL_BLOCK_SIZE) ?
_adjust2($rhInfo->_SMALL_BLOCK_SIZE) : 6));
$rhInfo->_SMALL_SIZE = 0x1000;
$rhInfo->_PPS_SIZE = 0x80;
#1.Open File
#1.1 $sFile is Ref of scalar
if(is_resource($sFile)) {
$oIo=$sFile;
$rhInfo->_FILEH_ = $oIo;
}
#1.2 $sFile is a simple filename string
else {
$oIo=fopen("$sFile", "wb");
$rhInfo->_FILEH_ = $oIo;
}
$iBlk = 0;
#1. Make an array of PPS (for Save)
$aList=array();
$list=array(&$this);
if($bNoAs) {
$this->_savePpsSetPnt2($list, $aList, $rhInfo);
} else {
$this->_savePpsSetPnt($list, $aList, $rhInfo);
}
list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList, $rhInfo);
#2.Save Header
$this->_saveHeader($rhInfo, $iSBDcnt, $iBBcnt, $iPPScnt);
#3.Make Small Data string (write SBD)
$sSmWk = $this->_makeSmallData($aList, $rhInfo);
$this->Data = $sSmWk; #Small Datas become RootEntry Data
#4. Write BB
$iBBlk = $iSBDcnt;
$this->_saveBigData($iBBlk, $aList, $rhInfo);
#5. Write PPS
$this->_savePps($aList, $rhInfo);
#6. Write BD and BDList and Adding Header informations
$this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt, $rhInfo);
#7.Close File
fclose($rhInfo->_FILEH_);
}
#------------------------------------------------------------------------------
# _calcSize (OLE::Storage_Lite::PPS)
#------------------------------------------------------------------------------
function _calcSize(&$raList, $rhInfo) {
#0. Calculate Basic Setting
$iSBDcnt=0;
$iBBcnt=0;
$iPPScnt = 0;
$iSmallLen = 0;
$iSBcnt = 0;
for ($c=0;$c<sizeof($raList);$c++) {
$oPps=&$raList[$c];
if($oPps->Type==PpsType_File) {
$oPps->Size = $oPps->_DataLen(); #Mod
if($oPps->Size < $rhInfo->_SMALL_SIZE) {
$iSBcnt += floor($oPps->Size / $rhInfo->_SMALL_BLOCK_SIZE) +
(($oPps->Size % $rhInfo->_SMALL_BLOCK_SIZE) ? 1 : 0);
} else {
$iBBcnt +=
(floor($oPps->Size/ $rhInfo->_BIG_BLOCK_SIZE) +
(($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE)? 1: 0));
}
}
}
$iSmallLen = $iSBcnt * $rhInfo->_SMALL_BLOCK_SIZE;
$iSlCnt = floor($rhInfo->_BIG_BLOCK_SIZE / LongIntSize);
$iSBDcnt = floor($iSBcnt / $iSlCnt)+ (($iSBcnt % $iSlCnt) ? 1 : 0);
$iBBcnt += (floor($iSmallLen/ $rhInfo->_BIG_BLOCK_SIZE) +
(( $iSmallLen% $rhInfo->_BIG_BLOCK_SIZE) ? 1 : 0));
$iCnt = sizeof($raList);
$iBdCnt = $rhInfo->_BIG_BLOCK_SIZE/PpsSize;
$iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt) ? 1 : 0));
return array($iSBDcnt, $iBBcnt, $iPPScnt);
}
#------------------------------------------------------------------------------
# _adjust2 (OLE::Storage_Lite::PPS::Root)
#------------------------------------------------------------------------------
function _adjust2($i2) {
$iWk = log($i2)/log(2);
return ($iWk > int($iWk)) ? floor($iWk)+1 : $iWk;
}
#------------------------------------------------------------------------------
# _saveHeader (OLE::Storage_Lite::PPS::Root)
#------------------------------------------------------------------------------
function _saveHeader($rhInfo, $iSBDcnt, $iBBcnt, $iPPScnt) {
$FILE = $rhInfo->_FILEH_;
#0. Calculate Basic Setting
$iBlCnt = $rhInfo->_BIG_BLOCK_SIZE / LongIntSize;
$i1stBdL = ($rhInfo->_BIG_BLOCK_SIZE - 0x4C) / LongIntSize;
$iBdExL = 0;
$iAll = $iBBcnt + $iPPScnt + $iSBDcnt;
$iAllW = $iAll;
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
$iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt) ? 1 : 0);
//my $i;
#0.1 Calculate BD count
if ($iBdCnt > $i1stBdL) {
// TODO: is do-while correct here?
do {
$iBdExL++;
$iAllW++;
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt) ? 1 : 0);
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt) ? 1 : 0);
} while($iBdCnt > ($iBdExL*$iBlCnt+ $i1stBdL));
}
#1.Save Header
fputs($FILE,
"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1".
"\x00\x00\x00\x00".
"\x00\x00\x00\x00".
"\x00\x00\x00\x00".
"\x00\x00\x00\x00".
pack("v", 0x3b).
pack("v", 0x03).
pack("v", -2).
pack("v", 9).
pack("v", 6).
pack("v", 0).
"\x00\x00\x00\x00".
"\x00\x00\x00\x00".
pack("V", $iBdCnt).
pack("V", $iBBcnt+$iSBDcnt). #ROOT START
pack("V", 0).
pack("V", 0x1000).
pack("V", 0). #Small Block Depot
pack("V", 1)
);
#2. Extra BDList Start, Count
if($iBdCnt < $i1stBdL) {
fputs($FILE,
pack("V", -2). #Extra BDList Start
pack("V", 0) #Extra BDList Count
);
} else {
fputs($FILE,
pack("V", $iAll+$iBdCnt).
pack("V", $iBdExL)
);
}
#3. BDList
for ($i=0;($i<$i1stBdL) && ($i < $iBdCnt); $i++) {
fputs($FILE, pack("V", $iAll+$i));
}
if ($i<$i1stBdL) {
// TODO: Check, if str_repeat is binary safe
fputs($FILE, str_repeat((pack("V", -1)), ($i1stBdL-$i)));
}
}
#------------------------------------------------------------------------------
# _saveBigData (OLE::Storage_Lite::PPS)
#------------------------------------------------------------------------------
function _saveBigData(&$iStBlk, &$raList, $rhInfo) {
//return;//!!!
$iRes = 0;
$FILE = $rhInfo->_FILEH_;
#1.Write Big (ge 0x1000) Data into Block
for ($c=0;$c<sizeof($raList);$c++) {
$oPps=&$raList[$c];
if($oPps->Type!=PpsType_Dir) {
#print "PPS: $oPps DEF:", defined($oPps->{Data}), "\n";
$oPps->Size = $oPps->_DataLen(); #Mod
if(($oPps->Size >= $rhInfo->_SMALL_SIZE) ||
(($oPps->Type == PpsType_Root) && $oPps->Data!==false)) {
#1.1 Write Data
#Check for update
if($oPps->_PPS_FILE) {
//my $sBuff;
$iLen = 0;
fseek($oPps->_PPS_FILE, 0, SEEK_SET); #To The Top
while ($sBuff=fread($oPps->_PPS_FILE, 4096)) {
$iLen += length($sBuff);
fputs($FILE, $sBuff); #Check for update
}
} else {
fputs($FILE, $oPps->Data);
}
if ($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE) {
// TODO: Check, if str_repeat() is binary safe
fputs($FILE, str_repeat("\x00",
($rhInfo->_BIG_BLOCK_SIZE -
($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE)))
);
}
#1.2 Set For PPS
$oPps->StartBlock = $iStBlk;
$iStBlk +=
(floor($oPps->Size/ $rhInfo->_BIG_BLOCK_SIZE) +
(($oPps->Size % $rhInfo->_BIG_BLOCK_SIZE) ? 1 : 0));
}
}
}
}
#------------------------------------------------------------------------------
# _savePps (OLE::Storage_Lite::PPS::Root)
#------------------------------------------------------------------------------
function _savePps(&$raList, $rhInfo)
{
#0. Initial
$FILE = $rhInfo->_FILEH_;
#2. Save PPS
for ($c=0;$c<sizeof($raList);$c++) {
$oItem=&$raList[$c];
$oItem->_savePpsWk($rhInfo);
}
#3. Adjust for Block
$iCnt = sizeof($raList);
$iBCnt = $rhInfo->_BIG_BLOCK_SIZE / $rhInfo->_PPS_SIZE;
if($iCnt % $iBCnt) {
fputs($FILE, str_repeat("\x00", (($iBCnt - ($iCnt % $iBCnt)) * $rhInfo->_PPS_SIZE)));
}
return (floor($iCnt / $iBCnt) + (($iCnt % $iBCnt) ? 1 : 0));
}
#------------------------------------------------------------------------------
# _savePpsSetPnt2 (OLE::Storage_Lite::PPS::Root)
# For Test
#------------------------------------------------------------------------------
function _savePpsSetPnt2(&$aThis, &$raList, $rhInfo) {
#1. make Array as Children-Relations
#1.1 if No Children
if (!is_array($aThis) || sizeof($aThis)==0) {
return 0xFFFFFFFF;
} elseif (sizeof($aThis)==1) {
#1.2 Just Only one
array_push($raList, &$aThis[0]);
$aThis[0]->No = sizeof($raList)-1;
$aThis[0]->PrevPps = 0xFFFFFFFF;
$aThis[0]->NextPps = 0xFFFFFFFF;
$aThis[0]->DirPps = $this->_savePpsSetPnt2($aThis[0]->Child, $raList, $rhInfo);
return $aThis[0]->No;
} else {
#1.3 Array
$iCnt = sizeof($aThis);
#1.3.1 Define Center
$iPos = 0; #int($iCnt/ 2); #$iCnt
$aWk = $aThis;
$aPrev = (sizeof($aThis) > 2) ? array_splice($aWk, 1, 1) : array(); #$iPos);
$aNext = array_splice($aWk, 1); #, $iCnt - $iPos -1);
$aThis[$iPos]->PrevPps = $this->_savePpsSetPnt2($aPrev, $raList, $rhInfo);
array_push($raList, $aThis[$iPos]);
$aThis[$iPos]->No = sizeof($raList)-1;
#1.3.2 Devide a array into Previous,Next
$aThis[$iPos]->NextPps = $this->_savePpsSetPnt2($aNext, $raList, $rhInfo);
$aThis[$iPos]->DirPps = $this->_savePpsSetPnt2($aThis[$iPos]->Child, $raList, $rhInfo);
return $aThis[$iPos]->No;
}
}
#------------------------------------------------------------------------------
# _savePpsSetPnt2 (OLE::Storage_Lite::PPS::Root)
# For Test
#------------------------------------------------------------------------------
function _savePpsSetPnt2s(&$aThis, &$raList, $rhInfo) {
#1. make Array as Children-Relations
#1.1 if No Children
if (!is_array($aThis) || sizeof($aThis)==0) {
return 0xFFFFFFFF;
} elseif (sizeof($aThis)==1) {
#1.2 Just Only one
array_push($raList, &$aThis[0]);
$aThis[0]->No = sizeof($raList)-1;
$aThis[0]->PrevPps = 0xFFFFFFFF;
$aThis[0]->NextPps = 0xFFFFFFFF;
$aThis[0]->DirPps = $this->_savePpsSetPnt2($aThis[0]->Child, $raList, $rhInfo);
return $aThis[0]->No;
} else {
#1.3 Array
$iCnt = sizeof($aThis);
#1.3.1 Define Center
$iPos = 0; #int($iCnt/ 2); #$iCnt
array_push($raList, $aThis[$iPos]);
$aThis[$iPos]->No = sizeof($raList)-1;
$aWk = $aThis;
#1.3.2 Devide a array into Previous,Next
$aPrev = array_splice($aWk, 0, $iPos);
$aNext = array_splice($aWk, 1, $iCnt - $iPos - 1);
$aThis[$iPos]->PrevPps = $this->_savePpsSetPnt2($aPrev, $raList, $rhInfo);
$aThis[$iPos]->NextPps = $this->_savePpsSetPnt2($aNext, $raList, $rhInfo);
$aThis[$iPos]->DirPps = $this->_savePpsSetPnt2($aThis[$iPos]->Child, $raList, $rhInfo);
return $aThis[$iPos]->No;
}
}
#------------------------------------------------------------------------------
# _savePpsSetPnt (OLE::Storage_Lite::PPS::Root)
#------------------------------------------------------------------------------
function _savePpsSetPnt(&$aThis, &$raList, $rhInfo) {
//print "yyy type: ".gettype($aThis)."<br>\n";
//print "yyy name: ".$aThis[0]->Name."<br>\n";
#1. make Array as Children-Relations
#1.1 if No Children
if (!is_array($aThis) || sizeof($aThis)==0) {
return 0xFFFFFFFF;
} elseif (sizeof($aThis)==1) {
#1.2 Just Only one
array_push($raList, &$aThis[0]);
$aThis[0]->No = sizeof($raList)-1;
$aThis[0]->PrevPps = 0xFFFFFFFF;
$aThis[0]->NextPps = 0xFFFFFFFF;
$aThis[0]->DirPps = $this->_savePpsSetPnt($aThis[0]->Child, $raList, $rhInfo);
return $aThis[0]->No;
} else {
#1.3 Array
$iCnt = sizeof($aThis);
#1.3.1 Define Center
$iPos = floor($iCnt/2); #$iCnt
array_push($raList, $aThis[$iPos]);
$aThis[$iPos]->No = sizeof($raList)-1;
$aWk = $aThis;
#1.3.2 Devide a array into Previous,Next
$aPrev = splice($aWk, 0, $iPos);
$aNext = splice($aWk, 1, $iCnt - $iPos - 1);
$aThis[$iPos]->PrevPps = $this->_savePpsSetPnt($aPrev, $raList, $rhInfo);
$aThis[$iPos]->NextPps = $this->_savePpsSetPnt($aNext, $raList, $rhInfo);
$aThis[$iPos]->DirPps = $this->_savePpsSetPnt($aThis[$iPos]->Child, $raList, $rhInfo);
return $aThis[$iPos]->No;
}
}
#------------------------------------------------------------------------------
# _savePpsSetPnt (OLE::Storage_Lite::PPS::Root)
#------------------------------------------------------------------------------
function _savePpsSetPnt1(&$aThis, &$raList, $rhInfo) {
#1. make Array as Children-Relations
#1.1 if No Children
if (!is_array($aThis) || sizeof($aThis)==0) {
return 0xFFFFFFFF;
} elseif (sizeof($aThis)==1) {
#1.2 Just Only one
array_push($raList, &$aThis[0]);
$aThis[0]->No = sizeof($raList)-1;
$aThis[0]->PrevPps = 0xFFFFFFFF;
$aThis[0]->NextPps = 0xFFFFFFFF;
$aThis[0]->DirPps = $this->_savePpsSetPnt($aThis[0]->Child, $raList, $rhInfo);
return $aThis[0]->No;
} else {
#1.3 Array
$iCnt = sizeof($aThis);
#1.3.1 Define Center
$iPos = floor($iCnt / 2); #$iCnt
array_push($raList, $aThis[$iPos]);
$aThis[$iPos]->No = sizeof($raList)-1;
$aWk = $aThis;
#1.3.2 Devide a array into Previous,Next
$aPrev = splice($aWk, 0, $iPos);
$aNext = splice($aWk, 1, $iCnt - $iPos - 1);
$aThis[$iPos]->PrevPps = $this->_savePpsSetPnt($aPrev, $raList, $rhInfo);
$aThis[$iPos]->NextPps = $this->_savePpsSetPnt($aNext, $raList, $rhInfo);
$aThis[$iPos]->DirPps = $this->_savePpsSetPnt($aThis[$iPos]->Child, $raList, $rhInfo);
return $aThis[$iPos]->No;
}
}
#------------------------------------------------------------------------------
# _saveBbd (OLE::Storage_Lite)
#------------------------------------------------------------------------------
function _saveBbd($iSbdSize, $iBsize, $iPpsCnt, $rhInfo) {
$FILE = $rhInfo->_FILEH_;
#0. Calculate Basic Setting
$iBbCnt = $rhInfo->_BIG_BLOCK_SIZE / LongIntSize;
$i1stBdL = ($rhInfo->_BIG_BLOCK_SIZE - 0x4C) / LongIntSize;
$iBdExL = 0;
$iAll = $iBsize + $iPpsCnt + $iSbdSize;
$iAllW = $iAll;
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
$iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0);
//my $i;
#0.1 Calculate BD count
if ($iBdCnt >$i1stBdL) {
// TODO: do-while correct here?
do {
$iBdExL++;
$iAllW++;
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt) ? 1 : 0);
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt) ? 1 : 0);
} while ($iBdCnt > ($iBdExL*$iBbCnt+$i1stBdL));
}
#1. Making BD
#1.1 Set for SBD
if($iSbdSize > 0) {
for ($i = 0; $i<($iSbdSize-1); $i++) {
fputs($FILE, pack("V", $i+1));
}
fputs($FILE, pack("V", -2));
}
#1.2 Set for B
for ($i = 0; $i<($iBsize-1); $i++) {
fputs($FILE, pack("V", $i+$iSbdSize+1));
}
fputs($FILE, pack("V", -2));
#1.3 Set for PPS
for ($i = 0; $i<($iPpsCnt-1); $i++) {
fputs($FILE, pack("V", $i+$iSbdSize+$iBsize+1));
}
fputs($FILE, pack("V", -2));
#1.4 Set for BBD itself ( 0xFFFFFFFD : BBD)
for ($i=0; $i<$iBdCnt;$i++) {
fputs($FILE, pack("V", 0xFFFFFFFD));
}
#1.5 Set for ExtraBDList
for ($i=0; $i<$iBdExL;$i++) {
fputs($FILE, pack("V", 0xFFFFFFFC));
}
#1.6 Adjust for Block
if(($iAllW + $iBdCnt) % $iBbCnt) {
fputs($FILE, str_repeat(pack("V", -1), ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt))));
}
#2.Extra BDList
if($iBdCnt > $i1stBdL) {
$iN=0;
$iNb=0;
for ($i=$i1stBdL;$i<$iBdCnt; $i++, $iN++) {
if($iN>=($iBbCnt-1)) {
$iN = 0;
$iNb++;
fputs($FILE, pack("V", $iAll+$iBdCnt+$iNb));
}
fputs($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i));
}
if(($iBdCnt-$i1stBdL) % ($iBbCnt-1)) {
fputs($FILE, str_repeat(pack("V", -1), (($iBbCnt-1) - (($iBdCnt-$i1stBdL) % ($iBbCnt-1)))));
}
fputs($FILE, pack("V", -2));
}
}
}
?>

View File

@@ -31,6 +31,7 @@ class writeexcel_biffwriter {
var $_data;
var $_datasize;
var $_limit;
var $_debug;
/*
* Constructor

View File

@@ -110,7 +110,7 @@ class writeexcel_format {
// Set properties passed to writeexcel_workbook::addformat()
if (sizeof($_)>0) {
call_user_method_array('set_properties', $this, $_);
call_user_func_array(array(&$this, 'set_properties'), $_);
}
}
@@ -119,7 +119,9 @@ class writeexcel_format {
*/
function copy($other) {
$xf = $this->_xf_index; // Backup XF index
$this = $other; // Copy properties
foreach ($other as $key->$value) {
$this->{$key} = $value;
}
$this->_xf_index = $xf; // Restore XF index
}

View File

@@ -36,20 +36,34 @@
* Spreadsheet::WriteExcel was written by John McNamara, jmcnamara@cpan.org
*/
define('SPREADSHEET_EXCEL_WRITER_ADD',"+");
// @const SPREADSHEET_EXCEL_WRITER_ADD token identifier for character "+"
define('SPREADSHEET_EXCEL_WRITER_SUB',"-");
// @const SPREADSHEET_EXCEL_WRITER_SUB token identifier for character "-"
define('SPREADSHEET_EXCEL_WRITER_MUL',"*");
// @const SPREADSHEET_EXCEL_WRITER_MUL token identifier for character "*"
define('SPREADSHEET_EXCEL_WRITER_DIV',"/");
// @const SPREADSHEET_EXCEL_WRITER_DIV token identifier for character "/"
define('SPREADSHEET_EXCEL_WRITER_OPEN',"(");
// @const SPREADSHEET_EXCEL_WRITER_OPEN token identifier for character "("
define('SPREADSHEET_EXCEL_WRITER_CLOSE',")");
// @const SPREADSHEET_EXCEL_WRITER_CLOSE token identifier for character ")"
define('SPREADSHEET_EXCEL_WRITER_COMA',",");
// @const SPREADSHEET_EXCEL_WRITER_COMA token identifier for character ","
define('SPREADSHEET_EXCEL_WRITER_ADD',"+");
// @const SPREADSHEET_EXCEL_WRITER_ADD token identifier for character "+"
define('SPREADSHEET_EXCEL_WRITER_SUB',"-");
// @const SPREADSHEET_EXCEL_WRITER_SUB token identifier for character "-"
define('SPREADSHEET_EXCEL_WRITER_MUL',"*");
// @const SPREADSHEET_EXCEL_WRITER_MUL token identifier for character "*"
define('SPREADSHEET_EXCEL_WRITER_DIV',"/");
// @const SPREADSHEET_EXCEL_WRITER_DIV token identifier for character "/"
define('SPREADSHEET_EXCEL_WRITER_OPEN',"(");
// @const SPREADSHEET_EXCEL_WRITER_OPEN token identifier for character "("
define('SPREADSHEET_EXCEL_WRITER_CLOSE',")");
// @const SPREADSHEET_EXCEL_WRITER_CLOSE token identifier for character ")"
define('SPREADSHEET_EXCEL_WRITER_COMA',",");
// @const SPREADSHEET_EXCEL_WRITER_COMA token identifier for character ","
define('SPREADSHEET_EXCEL_WRITER_SCOLON',";");
// @const SPREADSHEET_EXCEL_WRITER_SCOLON token identifier for character ";"
define('SPREADSHEET_EXCEL_WRITER_GT',">");
// @const SPREADSHEET_EXCEL_WRITER_GT token identifier for character ">"
define('SPREADSHEET_EXCEL_WRITER_LT',"<");
// @const SPREADSHEET_EXCEL_WRITER_LT token identifier for character "<"
define('SPREADSHEET_EXCEL_WRITER_LE',"<=");
// @const SPREADSHEET_EXCEL_WRITER_LE token identifier for character "<="
define('SPREADSHEET_EXCEL_WRITER_GE',">=");
// @const SPREADSHEET_EXCEL_WRITER_GE token identifier for character ">="
define('SPREADSHEET_EXCEL_WRITER_EQ',"=");
// @const SPREADSHEET_EXCEL_WRITER_EQ token identifier for character "="
define('SPREADSHEET_EXCEL_WRITER_NE',"<>");
// @const SPREADSHEET_EXCEL_WRITER_NE token identifier for character "<>"
class writeexcel_formula {
@@ -148,11 +162,6 @@ function parse_formula() {
return $str;
}
# Build the parse tree for the formula
$this->_formula = $formula;
$this->_current_char = 0;
function isError($data) {
return (bool)(is_object($data) &&
(get_class($data) == 'pear_error' ||
@@ -173,33 +182,103 @@ function isError($data) {
*
* @access private
*/
/**
function _initializeHashes()
{
// The Excel ptg indices
$this->ptg = array(
* @author Xavier Noguer <xnoguer@rezebra.com>
* @category FileFormats
* @package Spreadsheet_Excel_Writer
*/
/**
* Initialize the ptg and function hashes.
*
* @access private
*/
function _initializeHashes()
{
// The Excel ptg indices
$this->ptg = array(
'ptgExp' => 0x01,
'ptgTbl' => 0x02,
'ptgAdd' => 0x03,
'ptgSub' => 0x04,
'ptgMul' => 0x05,
'ptgDiv' => 0x06,
'ptgPower' => 0x07, 'ptgConcat' => 0x08,
'ptgLT' => 0x09,
'ptgLE' => 0x0A,
'ptgExp' => 0x01,
'ptgTbl' => 0x02,
'ptgAdd' => 0x03,
'ptgSub' => 0x04,
'ptgMul' => 0x05,
'ptgDiv' => 0x06,
'ptgPower' => 0x07, 'ptgConcat' => 0x08,
'ptgLT' => 0x09,
'ptgLE' => 0x0A,
'ptgEQ' => 0x0B,
'ptgGE' => 0x0C,
'ptgGT' => 0x0D,
'ptgNE' => 0x0E,
'ptgIsect' => 0x0F,
'ptgUnion' => 0x10,
'ptgRange' => 0x11,
'ptgUplus' => 0x12,
'ptgUminus' => 0x13,
'ptgPercent' => 0x14,
'ptgParen' => 0x15,
'ptgMissArg' => 0x16,
'ptgStr' => 0x17,
'ptgAttr' => 0x19,
'ptgSheet' => 0x1A,
'ptgEndSheet' => 0x1B,
'ptgErr' => 0x1C,
'ptgBool' => 0x1D,
'ptgInt' => 0x1E,
'ptgNum' => 0x1F,
'ptgArray' => 0x20,
'ptgFunc' => 0x21,
'ptgFuncVar' => 0x22,
'ptgName' => 0x23,
'ptgRef' => 0x24,
'ptgArea' => 0x25,
'ptgMemArea' => 0x26,
'ptgMemErr' => 0x27,
'ptgMemNoMem' => 0x28,
'ptgMemFunc' => 0x29,
'ptgRefErr' => 0x2A,
'ptgAreaErr' => 0x2B,
'ptgRefN' => 0x2C,
'ptgAreaN' => 0x2D,
'ptgMemAreaN' => 0x2E,
'ptgMemNoMemN' => 0x2F,
'ptgNameX' => 0x39,
'ptgRef3d' => 0x3A,
'ptgArea3d' => 0x3B,
'ptgRefErr3d' => 0x3C,
'ptgAreaErr3d' => 0x3D,
'ptgArrayV' => 0x40,
'ptgFuncV' => 0x41,
'ptgFuncVarV' => 0x42,
'ptgNameV' => 0x43,
'ptgRefV' => 0x44,
'ptgAreaV' => 0x45,
'ptgMemAreaV' => 0x46,
'ptgMemErrV' => 0x47,
'ptgMemNoMemV' => 0x48,
'ptgMemFuncV' => 0x49,
'ptgRefErrV' => 0x4A,
'ptgAreaErrV' => 0x4B,
'ptgRefNV' => 0x4C,
'ptgAreaNV' => 0x4D,
'ptgMemAreaNV' => 0x4E,
'ptgMemNoMemN' => 0x4F,
'ptgFuncCEV' => 0x58,
'ptgNameXV' => 0x59,
'ptgRef3dV' => 0x5A,
'ptgArea3dV' => 0x5B, 'ptgRefErr3dV' => 0x5C,
'ptgAreaErr3d' => 0x5D,
'ptgArrayA' => 0x60,
'ptgFuncA' => 0x61,
'ptgFuncVarA' => 0x62,
'ptgNameA' => 0x63, 'ptgRefA' => 0x64,
'ptgAreaA' => 0x65,
'ptgMemAreaA' => 0x66,
'ptgMemErrA' => 0x67,
'ptgMemNoMemA' => 0x68,
'ptgMemFuncA' => 0x69,
'ptgRefErrA' => 0x6A,
'ptgAreaErrA' => 0x6B,
'ptgRefNA' => 0x6C,
'ptgAreaNA' => 0x6D,
'ptgMemAreaNA' => 0x6E,
'ptgMemNoMemN' => 0x6F,
'ptgFuncCEA' => 0x78,
'ptgNameXA' => 0x79,
'ptgRef3dA' => 0x7A,
'ptgArea3dA' => 0x7B,
'ptgRefErr3dA' => 0x7C,
'ptgAreaErr3d' => 0x7D
);
// Thanks to Michael Meeks and Gnumeric for the initial arg values.
@@ -453,37 +532,50 @@ function _initializeHashes() {
* @return mixed the converted token on success. PEAR_Error if the token
* is not recognized
*/
'AVEDEV' => array( 269, -1, 0, 0 ),
'BETADIST' => array( 270, -1, 1, 0 ),
function _convert($token)
{
if (preg_match('/^"[^"]{0,255}"$/', $token))
{
return $this->_convertString($token);
'BETAINV' => array( 272, -1, 1, 0 ),
}
elseif (is_numeric($token))
{
return $this->_convertNumber($token);
}
// match references like A1 or $A$1
'COMBIN' => array( 276, 2, 1, 0 ),
elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token))
{
return $this->_convertRef2d($token);
}
// match external references like Sheet1:Sheet2!A1
'EXPONDIST' => array( 280, 3, 1, 0 ),
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-Ia-i]?[A-Za-z](\d+)$/",$token))
{
return $this->_convertRef3d($token);
}
// match ranges like A1:B2
'FISHERINV' => array( 284, 1, 1, 0 ),
elseif (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?\d+\:\$?[A-Ia-i]?[A-Za-z]\$?\d+$/',$token))
{
return $this->_convertRange2d($token);
}
// match ranges like A1..B2
'CEILING' => array( 288, 2, 1, 0 ),
elseif (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?\d+\.\.\$?[A-Ia-i]?[A-Za-z]\$?\d+$/',$token))
{
return $this->_convertRange2d($token);
}
// match external ranges like Sheet1:Sheet2!A1:B2
'NEGBINOMDIST' => array( 292, 3, 1, 0 ),
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/",$token))
{
return $this->_convertRange3d($token);
}
// match external ranges like 'Sheet1:Sheet2'!A1:B2
'NORMSINV' => array( 296, 1, 1, 0 ),
elseif (preg_match("/^'[A-Za-z0-9_ ]+(\:[A-Za-z0-9_ ]+)?'\!([A-Ia-i]?[A-Za-z])?(\d+)\:([A-Ia-i]?[A-Za-z])?(\d+)$/",$token))
{
return $this->_convertRange3d($token);
}
'PERMUT' => array( 299, 2, 1, 0 ),
elseif (isset($this->ptg[$token])) // operators (including parentheses)
{
return pack("C", $this->ptg[$token]);
}
// commented so argument number can be processed correctly. See toReversePolish().
@@ -492,7 +584,8 @@ function _convert($token) {
return($this->_convertFunction($token,$this->_func_args));
}*/
// if it's an argument, ignore the token (the argument remains)
'COVAR' => array( 308, 2, 2, 0 ),
elseif ($token == 'arg')
{
return '';
}
// TODO: use real error codes
@@ -505,13 +598,15 @@ function _convert($token) {
* @access private
* @param mixed $num an integer or double for conversion to its ptg value
*/
'SUMSQ' => array( 321, -1, 0, 0 ),
function _convertNumber($num)
{
// Integer in the range 0..2**16-1
if ((preg_match("/^\d+$/",$num)) and ($num <= 65535)) {
return(pack("Cv", $this->ptg['ptgInt'], $num));
'QUARTILE' => array( 327, 2, 0, 0 ),
}
else { // A float
if ($this->_byte_order) { // if it's Big Endian
$num = strrev($num);
}
@@ -525,7 +620,8 @@ function _convertNumber($num) {
* @access private
* @param string $string A string for conversion to its ptg value
*/
'ROMAN' => array( 354, -1, 1, 0 )
function _convertString($string)
{
// chop away beggining and ending quotes
$string = substr($string, 1, strlen($string) - 2);
return pack("CC", $this->ptg['ptgStr'], strlen($string)).$string;
@@ -540,7 +636,8 @@ function _convertString($string) {
* @param integer $num_args The number of arguments the function receives.
* @return string The packed ptg for the function
*/
{
function _convertFunction($token, $num_args)
{
$args = $this->_functions[$token][1];
$volatile = $this->_functions[$token][3];
@@ -560,15 +657,18 @@ function _convertFunction($token, $num_args) {
* @access private
* @param string $range An Excel range in the A1:A2 or A1..A2 format.
*/
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/",$token))
function _convertRange2d($range)
{
$class = 2; // as far as I know, this is magick.
// Split the range into 2 cell refs
// match ranges like A1..B2
if (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)\:\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$range)) {
list($cell1, $cell2) = split(':', $range);
{
}
elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)\.\.\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$range)) {
list($cell1, $cell2) = split('\.\.', $range);
}
}
else {
// TODO: use real error codes
trigger_error("Unknown range separator", E_USER_ERROR);
}
@@ -588,11 +688,14 @@ function _convertRange2d($range) {
// The ptg value depends on the class of the ptg.
if ($class == 0) {
$ptgArea = pack("C", $this->ptg['ptgArea']);
// if it's an argument, ignore the token (the argument remains)
}
elseif ($class == 1) {
$ptgArea = pack("C", $this->ptg['ptgAreaV']);
{
}
elseif ($class == 2) {
$ptgArea = pack("C", $this->ptg['ptgAreaA']);
}
}
else {
// TODO: use real error codes
trigger_error("Unknown class $class", E_USER_ERROR);
}
@@ -606,7 +709,8 @@ function _convertRange2d($range) {
* @access private
* @param string $token An Excel range in the Sheet1!A1:A2 format.
*/
// Integer in the range 0..2**16-1
function _convertRange3d($token)
{
$class = 2; // as far as I know, this is magick.
// Split the ref at the ! symbol
@@ -622,7 +726,8 @@ function _convertRange3d($token) {
list($cell1, $cell2) = split(':', $range);
// Convert the cell references
* @access private
if (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $cell1))
{
$cell_array1 = $this->_cellToPackedRowcol($cell1);
if ($this->isError($cell_array1)) {
return $cell_array1;
@@ -633,7 +738,8 @@ function _convertRange3d($token) {
return $cell_array2;
}
list($row2, $col2) = $cell_array2;
* Convert a function to a ptgFunc or ptgFuncVarV depending on the number of
}
else { // It's a columns range (like 26:27)
$cells_array = $this->_rangeToPackedRange($cell1.':'.$cell2);
if ($this->isError($cells_array)) {
return $cells_array;
@@ -644,11 +750,14 @@ function _convertRange3d($token) {
// The ptg value depends on the class of the ptg.
if ($class == 0) {
$ptgArea = pack("C", $this->ptg['ptgArea3d']);
$volatile = $this->_functions[$token][3];
}
elseif ($class == 1) {
$ptgArea = pack("C", $this->ptg['ptgArea3dV']);
// Fixed number of args eg. TIME($i,$j,$k).
}
elseif ($class == 2) {
$ptgArea = pack("C", $this->ptg['ptgArea3dA']);
return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]);
}
else {
trigger_error("Unknown class $class", E_USER_ERROR);
}
@@ -662,7 +771,8 @@ function _convertRange3d($token) {
* @param string $cell An Excel cell reference
* @return string The cell in packed() format with the corresponding ptg
*/
function _convertRange2d($range)
function _convertRef2d($cell)
{
$class = 2; // as far as I know, this is magick.
// Convert the cell reference
@@ -675,11 +785,14 @@ function _convertRef2d($cell) {
// The ptg value depends on the class of the ptg.
if ($class == 0) {
$ptgRef = pack("C", $this->ptg['ptgRef']);
trigger_error("Unknown range separator", E_USER_ERROR);
}
elseif ($class == 1) {
$ptgRef = pack("C", $this->ptg['ptgRefV']);
}
elseif ($class == 2) {
$ptgRef = pack("C", $this->ptg['ptgRefA']);
$cell_array1 = $this->_cellToPackedRowcol($cell1);
}
else {
// TODO: use real error codes
trigger_error("Unknown class $class",E_USER_ERROR);
}
@@ -694,7 +807,8 @@ function _convertRef2d($cell) {
* @param string $cell An Excel cell reference
* @return string The cell in packed() format with the corresponding ptg
*/
elseif ($class == 1) {
function _convertRef3d($cell)
{
$class = 2; // as far as I know, this is magick.
// Split the ref at the ! symbol
@@ -716,7 +830,8 @@ function _convertRef3d($cell) {
$ptgRef = pack("C", $this->ptg['ptgRef3dV']);
} elseif ($class == 2) {
$ptgRef = pack("C", $this->ptg['ptgRef3dA']);
$class = 2; // as far as I know, this is magick.
}
else {
trigger_error("Unknown class $class", E_USER_ERROR);
}
@@ -736,7 +851,8 @@ function _packExtRef($ext_ref) {
$ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any.
// Check if there is a sheet range eg., Sheet1:Sheet2.
}
if (preg_match("/:/", $ext_ref))
{
list($sheet_name1, $sheet_name2) = split(':', $ext_ref);
$sheet1 = $this->_getSheetIndex($sheet_name1);
@@ -752,7 +868,8 @@ function _packExtRef($ext_ref) {
if ($sheet1 > $sheet2) {
list($sheet1, $sheet2) = array($sheet2, $sheet1);
}
// The ptg value depends on the class of the ptg.
}
else { // Single sheet name only.
$sheet1 = $this->_getSheetIndex($ext_ref);
if ($sheet1 == -1) {
trigger_error("Unknown sheet name $ext_ref in formula",E_USER_ERROR);
@@ -774,10 +891,12 @@ function _packExtRef($ext_ref) {
* @access private
* @return integer
*/
* @return string The cell in packed() format with the corresponding ptg
function _getSheetIndex($sheet_name)
{
if (!isset($this->_ext_sheets[$sheet_name])) {
return -1;
{
}
else {
return $this->_ext_sheets[$sheet_name];
}
}
@@ -790,7 +909,8 @@ function _getSheetIndex($sheet_name) {
* @param string $name The name of the worksheet being added
* @param integer $index The index of the worksheet being added
*/
}
function set_ext_sheet($name, $index)
{
$this->_ext_sheets[$name] = $index;
}
@@ -801,7 +921,8 @@ function setExtSheet($name, $index) {
* @param string $cell The Excel cell reference to be packed
* @return array Array containing the row and column in packed() format
*/
return $ptgRef.$row.$col;
function _cellToPackedRowcol($cell)
{
$cell = strtoupper($cell);
list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell);
if ($col >= 256) {
@@ -829,7 +950,8 @@ function _cellToPackedRowcol($cell) {
* @param string $range The Excel range to be packed
* @return array Array containing (row1,col1,row2,col2) in packed() format
*/
if ($class == 0) {
function _rangeToPackedRange($range)
{
preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match);
// return absolute rows if there is a $ in the ref
$row1_rel = empty($match[1]) ? 1 : 0;
@@ -869,7 +991,8 @@ function _rangeToPackedRange($range) {
* @param string $cell The Excel cell reference in A1 format.
* @return array
*/
// Reverse max and min sheet numbers if necessary
function _cellToRowcol($cell)
{
preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match);
// return absolute column if there is a $ in the ref
$col_rel = empty($match[1]) ? 1 : 0;
@@ -880,7 +1003,8 @@ function _cellToRowcol($cell) {
// Convert base26 column string to a number.
$expn = strlen($col_ref) - 1;
$col = 0;
}
for ($i=0; $i < strlen($col_ref); $i++)
{
$col += (ord($col_ref{$i}) - ord('A') + 1) * pow(26, $expn);
$expn--;
}
@@ -897,10 +1021,12 @@ function _cellToRowcol($cell) {
*
* @access private
*/
{
function _advance()
{
$i = $this->_current_char;
// eat up white spaces
}
if ($i < strlen($this->_formula))
{
while ($this->_formula{$i} == " ") {
$i++;
}
@@ -909,14 +1035,17 @@ function _advance() {
}
$token = "";
}
*
while ($i < strlen($this->_formula))
{
$token .= $this->_formula{$i};
if ($i < strlen($this->_formula) - 1) {
$this->_lookahead = $this->_formula{$i+1};
*/
}
else {
$this->_lookahead = '';
}
$this->_ext_sheets[$name] = $index;
if ($this->_match($token) != '')
{
//if ($i < strlen($this->_formula) - 1) {
// $this->_lookahead = $this->_formula{$i+1};
//}
@@ -926,7 +1055,8 @@ function _advance() {
}
if ($i < strlen($this->_formula) - 2) {
$this->_lookahead = $this->_formula{$i+2};
function _cellToPackedRowcol($cell)
}
else {
// if we run out of characters _lookahead becomes empty
$this->_lookahead = '';
}
@@ -942,8 +1072,10 @@ function _advance() {
* @param mixed $token The token to check.
* @return mixed The checked token or false on failure
*/
$col = pack('C', $col);
function _match($token)
{
switch($token)
{
case SPREADSHEET_EXCEL_WRITER_ADD:
return($token);
break;
@@ -998,43 +1130,51 @@ function _match($token) {
if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and
!ereg("[0-9]",$this->_lookahead) and
($this->_lookahead != ':') and ($this->_lookahead != '.') and
preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match);
($this->_lookahead != '!'))
{
return $token;
}
// If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1)
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-Ia-i]?[A-Za-z][0-9]+$/",$token) and
!ereg("[0-9]",$this->_lookahead) and
($this->_lookahead != ':') and ($this->_lookahead != '.'))
{
return $token;
}
// if it's a range (A1:A2)
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
{
!ereg("[0-9]",$this->_lookahead))
{
return $token;
}
// if it's a range (A1..A2)
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
// Convert 1-index to zero-index
!ereg("[0-9]",$this->_lookahead))
{
return $token;
}
// If it's an external range like Sheet1:Sheet2!A1:B2
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$token) and
}
!ereg("[0-9]",$this->_lookahead))
{
return $token;
}
// If it's an external range like 'Sheet1:Sheet2'!A1:B2
elseif (preg_match("/^'[A-Za-z0-9_ ]+(\:[A-Za-z0-9_ ]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$token) and
* @access private
!ereg("[0-9]",$this->_lookahead))
{
return $token;
}
// If it's a number (check that it's not a sheet name or range)
elseif (is_numeric($token) and
(!is_numeric($token.$this->_lookahead) or ($this->_lookahead == '')) and
if ($i < strlen($this->_formula))
($this->_lookahead != '!') and ($this->_lookahead != ':'))
{
return $token;
}
// If it's a string (of maximum 255 characters)
}
elseif (ereg("^\"[^\"]{0,255}\"$",$token))
{
return $token;
}
// if it's a function call
@@ -1051,7 +1191,8 @@ function _match($token) {
* @access public
* @param string $formula The formula to parse, without the initial equal sign (=).
*/
//if ($i < strlen($this->_formula) - 1) {
function parse($formula)
{
$this->_current_char = 0;
$this->_formula = $formula;
$this->_lookahead = $formula{1};
@@ -1069,47 +1210,59 @@ function parse($formula) {
* @access private
* @return mixed The parsed ptg'd tree
*/
function _condition()
{
$result = $this->_expression();
if ($this->isError($result)) {
return $result;
}
* @param mixed $token The token to check.
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_LT)
{
$this->_advance();
$result2 = $this->_expression();
if ($this->isError($result2)) {
return $result2;
}
$result = $this->_createTree('ptgLT', $result, $result2);
case SPREADSHEET_EXCEL_WRITER_ADD:
}
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_GT)
{
$this->_advance();
$result2 = $this->_expression();
if ($this->isError($result2)) {
return $result2;
}
$result = $this->_createTree('ptgGT', $result, $result2);
return($token);
}
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_LE)
{
$this->_advance();
$result2 = $this->_expression();
if ($this->isError($result2)) {
return $result2;
}
$result = $this->_createTree('ptgLE', $result, $result2);
break;
}
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_GE)
{
$this->_advance();
$result2 = $this->_expression();
if ($this->isError($result2)) {
return $result2;
}
$result = $this->_createTree('ptgGE', $result, $result2);
case SPREADSHEET_EXCEL_WRITER_COMA:
}
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_EQ)
{
$this->_advance();
$result2 = $this->_expression();
if ($this->isError($result2)) {
return $result2;
}
$result = $this->_createTree('ptgEQ', $result, $result2);
return($token);
}
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_NE)
{
$this->_advance();
$result2 = $this->_expression();
if ($this->isError($result2)) {
@@ -1127,9 +1280,11 @@ function _condition() {
* @access private
* @return mixed The parsed ptg'd tree
*/
case SPREADSHEET_EXCEL_WRITER_NE:
function _expression()
{
// If it's a string return a string node
break;
if (ereg("^\"[^\"]{0,255}\"$", $this->_current_token))
{
$result = $this->_createTree($this->_current_token, '', '');
$this->_advance();
return $result;
@@ -1139,15 +1294,20 @@ function _expression() {
return $result;
}
while (($this->_current_token == SPREADSHEET_EXCEL_WRITER_ADD) or
// If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1)
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-Ia-i]?[A-Za-z][0-9]+$/",$token) and
($this->_current_token == SPREADSHEET_EXCEL_WRITER_SUB))
{
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_ADD)
{
$this->_advance();
$result2 = $this->_term();
if ($this->isError($result2)) {
return $result2;
}
$result = $this->_createTree('ptgAdd', $result, $result2);
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
}
else
{
$this->_advance();
$result2 = $this->_term();
if ($this->isError($result2)) {
@@ -1167,7 +1327,8 @@ function _expression() {
* @see _fact()
* @return mixed The parsed ptg'd tree
*/
{
function _parenthesizedExpression()
{
$result = $this->_createTree('ptgParen', $this->_expression(), '');
return $result;
}
@@ -1179,21 +1340,26 @@ function _parenthesizedExpression() {
* @access private
* @return mixed The parsed ptg'd tree
*/
{
function _term()
{
$result = $this->_fact();
if ($this->isError($result)) {
return $result;
}
while (($this->_current_token == SPREADSHEET_EXCEL_WRITER_MUL) or
($this->_current_token == SPREADSHEET_EXCEL_WRITER_DIV)) {
return '';
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_MUL)
{
$this->_advance();
$result2 = $this->_fact();
if ($this->isError($result2)) {
return $result2;
}
$result = $this->_createTree('ptgMul', $result, $result2);
* @access public
}
else
{
$this->_advance();
$result2 = $this->_fact();
if ($this->isError($result2)) {
@@ -1216,8 +1382,10 @@ function _term() {
* @access private
* @return mixed The parsed ptg'd tree
*/
{
$result = $this->_expression();
function _fact()
{
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_OPEN)
{
$this->_advance(); // eat the "("
$result = $this->_parenthesizedExpression();
if ($this->_current_token != SPREADSHEET_EXCEL_WRITER_CLOSE) {
@@ -1225,37 +1393,51 @@ function _fact() {
}
$this->_advance(); // eat the ")"
return $result;
if ($this->isError($result2)) {
}
if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$this->_current_token))
{
// if it's a reference
$result = $this->_createTree($this->_current_token, '', '');
$this->_advance();
return $result;
elseif ($this->_current_token == SPREADSHEET_EXCEL_WRITER_GT)
}
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-Ia-i]?[A-Za-z][0-9]+$/",$this->_current_token))
{
// If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1)
$result = $this->_createTree($this->_current_token, '', '');
$this->_advance();
return $result;
return $result2;
}
}
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token) or
preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$this->_current_token))
{
// if it's a range
$result = $this->_current_token;
$this->_advance();
return $result;
$this->_advance();
}
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$this->_current_token))
{
// If it's an external range (Sheet1!A1:B2)
$result = $this->_current_token;
$this->_advance();
return $result;
$result = $this->_createTree('ptgLE', $result, $result2);
}
elseif (preg_match("/^'[A-Za-z0-9_ ]+(\:[A-Za-z0-9_ ]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$this->_current_token))
{
// If it's an external range ('Sheet1'!A1:B2)
$result = $this->_current_token;
$this->_advance();
return $result;
$result2 = $this->_expression();
}
elseif (is_numeric($this->_current_token))
{
$result = $this->_createTree($this->_current_token, '', '');
$this->_advance();
return $result;
$result = $this->_createTree('ptgGE', $result, $result2);
}
elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$this->_current_token))
{
// if it's a function call
$result = $this->_func();
return $result;
@@ -1270,17 +1452,21 @@ function _fact() {
*
* @access private
*/
if ($this->isError($result2)) {
function _func()
{
$num_args = 0; // number of arguments received
$function = $this->_current_token;
$this->_advance();
$this->_advance(); // eat the "("
return $result;
}
while ($this->_current_token != ')')
{
if ($num_args > 0)
{
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_COMA ||
$this->_current_token == SPREADSHEET_EXCEL_WRITER_SCOLON) {
$this->_advance(); // eat the ","
* Expr -> Term [("+" | "-") Term]
}
else {
trigger_error("Sintactic error: coma expected in ".
"function $function, {$num_args}<EFBFBD> arg", E_USER_ERROR);
}
@@ -1289,7 +1475,8 @@ function _func() {
return $result2;
}
$result = $this->_createTree('arg', $result, $result2);
{
}
else { // first argument
$result2 = $this->_condition();
if ($this->isError($result2)) {
return $result2;
@@ -1318,7 +1505,8 @@ function _func() {
* @param mixed $left The left array (sub-tree) or a final node.
* @param mixed $right The right array (sub-tree) or a final node.
*/
$result = $this->_createTree('ptgSub', $result, $result2);
function _createTree($value, $left, $right)
{
return(array('value' => $value, 'left' => $left, 'right' => $right));
}
@@ -1349,31 +1537,36 @@ function _createTree($value, $left, $right) {
* @param array $tree The optional tree to convert.
* @return string The tree in reverse polish notation
*/
return $result;
function toReversePolish($tree = array())
{
$polish = ""; // the string we are going to return
if (empty($tree)) { // If it's the first call use _parse_tree
$tree = $this->_parse_tree;
}
if (is_array($tree['left']))
{
$converted_tree = $this->toReversePolish($tree['left']);
if ($this->isError($converted_tree)) {
return $converted_tree;
}
$polish .= $converted_tree;
}
}
elseif ($tree['left'] != '') { // It's a final node
$converted_tree = $this->_convert($tree['left']);
if ($this->isError($converted_tree)) {
return $converted_tree;
}
$polish .= $converted_tree;
}
if ($this->isError($result2)) {
if (is_array($tree['right']))
{
$converted_tree = $this->toReversePolish($tree['right']);
if ($this->isError($converted_tree)) {
return $converted_tree;
}
$polish .= $converted_tree;
return $result;
}
elseif ($tree['right'] != '') { // It's a final node
$converted_tree = $this->_convert($tree['right']);
if ($this->isError($converted_tree)) {
return $converted_tree;
@@ -1385,11 +1578,13 @@ function toReversePolish($tree = array()) {
!preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and
!preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and
!is_numeric($tree['value']) and
* @return mixed The parsed ptg'd tree
!isset($this->ptg[$tree['value']]))
{
// left subtree for a function is always an array.
if ($tree['left'] != '') {
$left_tree = $this->toReversePolish($tree['left']);
if ($this->_current_token == SPREADSHEET_EXCEL_WRITER_OPEN)
}
else {
$left_tree = '';
}
if ($this->isError($left_tree)) {
@@ -1397,7 +1592,9 @@ function toReversePolish($tree = array()) {
}
// add it's left subtree and return.
return $left_tree.$this->_convertFunction($tree['value'], $tree['right']);
return $result;
}
else
{
$converted_tree = $this->_convert($tree['value']);
if ($this->isError($converted_tree)) {
return $converted_tree;

View File

@@ -45,6 +45,7 @@ class writeexcel_workbook extends writeexcel_biffwriter {
var $_sheetname;
var $_tmp_format;
var $_url_format;
var $_codepage;
var $_worksheets;
var $_sheetnames;
var $_formats;
@@ -77,6 +78,7 @@ function writeexcel_workbook($filename) {
$this->_sheetname = "Sheet";
$this->_tmp_format = $tmp_format;
$this->_url_format = false;
$this->_codepage = 0x04E4;
$this->_worksheets = array();
$this->_sheetnames = array();
$this->_formats = array();
@@ -411,6 +413,24 @@ function set_tempdir($tempdir) {
$this->_tempdir = $tempdir;
}
###############################################################################
#
# set_codepage()
#
# See also the _store_codepage method. This is used to store the code page, i.e.
# the character set used in the workbook.
#
function set_codepage($cp) {
if($cp==1)
$codepage = 0x04E4;
else if($cp==2)
$codepage = 0x8000;
if($codepage)
$this->_codepage = $codepage;
}
###############################################################################
#
# _store_workbook()
@@ -442,6 +462,8 @@ function _store_workbook() {
$this->_store_names(); # For print area and repeat rows
$this->_store_codepage();
$this->_store_window1();
$this->_store_1904();
@@ -499,6 +521,7 @@ function _store_OLE_file() {
while ($tmp = $sheet->get_data()) {
$OLE->write($tmp);
}
$sheet->cleanup();
}
}
@@ -1103,6 +1126,24 @@ function _store_palette() {
$this->_append($header . $data);
}
###############################################################################
#
# _store_codepage()
#
# Stores the CODEPAGE biff record.
#
function _store_codepage() {
$record = 0x0042; # Record identifier
$length = 0x0002; # Number of bytes to follow
$cv = $this->_codepage; # The code page
$header = pack("vv", $record, $length);
$data = pack("v", $cv);
$this->_append($header.$data);
}
}
?>

View File

@@ -43,6 +43,7 @@ class writeexcel_workbookbig extends writeexcel_workbook {
while ($data=$worksheet->get_data()) {
$file->append($data);
}
$worksheet->cleanup();
}
$ole=new ole_pps_root(false, false, array($file));

View File

@@ -38,6 +38,7 @@ class writeexcel_worksheet extends writeexcel_biffwriter {
var $_ext_sheets;
var $_using_tmpfile;
var $_tmpfilename;
var $_filehandle;
var $_fileclosed;
var $_offset;
@@ -100,6 +101,8 @@ class writeexcel_worksheet extends writeexcel_biffwriter {
var $_zoom;
var $_print_scale;
var $_debug;
/*
* Constructor. Creates a new Worksheet object from a BIFFwriter object
*/
@@ -122,6 +125,7 @@ class writeexcel_worksheet extends writeexcel_biffwriter {
$this->_ext_sheets = array();
$this->_using_tmpfile = 1;
$this->_tmpfilename = false;
$this->_filehandle = false;
$this->_fileclosed = 0;
$this->_offset = 0;
@@ -198,7 +202,8 @@ class writeexcel_worksheet extends writeexcel_biffwriter {
function _initialize() {
# Open tmp file for storing Worksheet data.
$fh=fopen(tempnam($this->_tempdir, "php_writeexcel"), "w+b");
$this->_tmpfilename=tempnam($this->_tempdir, "php_writeexcel");
$fh=fopen($this->_tmpfilename, "w+b");
if ($fh) {
# Store filehandle
@@ -206,6 +211,7 @@ function _initialize() {
} else {
# If tempfile() failed store data in memory
$this->_using_tmpfile = 0;
$this->_tmpfilename=false;
if ($this->_index == 0) {
$dir = $this->_tempdir;
@@ -307,9 +313,11 @@ function get_data() {
if ($this->_data!==false) {
$tmp=$this->_data;
$this->_data=false;
$fh = $this->_filehandle;
// The next data comes from the temporary file, so prepare
// it by putting the file pointer to the beginning
if ($this->_using_tmpfile) {
fseek($fh, 0, SEEK_SET);
fseek($this->_filehandle, 0, SEEK_SET);
}
if ($this->_debug) {
@@ -345,10 +353,20 @@ function get_data() {
}
}
# No data to return
# No more data to return
return false;
}
/* Remove the temporary file */
function cleanup() {
if ($this->_using_tmpfile) {
fclose($this->_filehandle);
unlink($this->_tmpfilename);
$this->_tmpfilename=false;
$this->_using_tmpfile=false;
}
}
/*
* Set this worksheet as a selected worksheet, i.e. the worksheet has
* its tab highlighted.
@@ -767,37 +785,37 @@ function write() {
# Match an array ref.
if (is_array($token)) {
return call_user_method_array('write_row', $this, $_);
return call_user_func_array(array(&$this, 'write_row'), $_);
}
# Match number
if (preg_match('/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/', $token)) {
return call_user_method_array('write_number', $this, $_);
return call_user_func_array(array(&$this, 'write_number'), $_);
}
# Match http, https or ftp URL
elseif (preg_match('|^[fh]tt?ps?://|', $token)) {
return call_user_method_array('write_url', $this, $_);
return call_user_func_array(array(&$this, 'write_url'), $_);
}
# Match mailto:
elseif (preg_match('/^mailto:/', $token)) {
return call_user_method_array('write_url', $this, $_);
return call_user_func_array(array(&$this, 'write_url'), $_);
}
# Match internal or external sheet link
elseif (preg_match('[^(?:in|ex)ternal:]', $token)) {
return call_user_method_array('write_url', $this, $_);
return call_user_func_array(array(&$this, 'write_url'), $_);
}
# Match formula
elseif (preg_match('/^=/', $token)) {
return call_user_method_array('write_formula', $this, $_);
return call_user_func_array(array(&$this, 'write_formula'), $_);
}
# Match blank
elseif ($token == '') {
array_splice($_, 2, 1); # remove the empty string from the parameter list
return call_user_method_array('write_blank', $this, $_);
return call_user_func_array(array(&$this, 'write_blank'), $_);
}
# Default: match string
else {
return call_user_method_array('write_string', $this, $_);
return call_user_func_array(array(&$this, 'write_string'), $_);
}
}
@@ -1069,6 +1087,7 @@ function _cell_to_rowcol($cell) {
function _encode_password($plaintext) {
$chars=preg_split('//', $plaintext, -1, PREG_SPLIT_NO_EMPTY);
$count=sizeof($chars);
$i=0;
for ($c=0;$c<sizeof($chars);$c++) {
$char=&$chars[$c];
@@ -1377,7 +1396,7 @@ function write_url() {
}
# Add start row and col to arg list
return call_user_method_array('write_url_range', $this,
return call_user_func_array(array(&$this, 'write_url_range'),
array_merge(array($_[0], $_[1]), $_));
}
@@ -1413,14 +1432,14 @@ function write_url_range() {
# Check for internal/external sheet links or default to web link
if (preg_match('[^internal:]', $url)) {
return call_user_method_array('_write_url_internal', $this, $_);
return call_user_func_array(array(&$this, '_write_url_internal'), $_);
}
if (preg_match('[^external:]', $url)) {
return call_user_method_array('_write_url_external', $this, $_);
return call_user_func_array(array(&$this, '_write_url_external'), $_);
}
return call_user_method_array('_write_url_web', $this, $_);
return call_user_func_array(array(&$this, '_write_url_web'), $_);
}
###############################################################################
@@ -1582,7 +1601,7 @@ function _write_url_external() {
# Network drives are different. We will handle them separately
# MS/Novell network drives and shares start with \\
if (preg_match('[^external:\\\\]', $_[4])) {
return call_user_method_array('_write_url_external_net', $this, $_);
return call_user_func_array(array(&$this, '_write_url_external_net'), $_);
}
$record = 0x01B8; # Record identifier
@@ -2075,15 +2094,13 @@ function _store_selection($_) {
# Frozen panes are specified in terms of a integer number of rows and columns.
# Thawed panes are specified in terms of Excel's units for rows and columns.
#
function _store_panes() {
$_=func_get_args();
function _store_panes($_) {
$record = 0x0041; # Record identifier
$length = 0x000A; # Number of bytes to follow
$y = $_[0] || 0; # Vertical split position
$x = $_[1] || 0; # Horizontal split position
$y = $_[0] ? $_[0] : 0; # Vertical split position
$x = $_[1] ? $_[1] : 0; # Horizontal split position
if (isset($_[2])) {
$rwTop = $_[2]; # Top row visible
}
@@ -2371,8 +2388,8 @@ function merge_cells() {
$cref = 1; # Number of refs
$rwFirst = $_[0]; # First row in reference
$colFirst = $_[1]; # First col in reference
$rwLast = $_[2] || $rwFirst; # Last row in reference
$colLast = $_[3] || $colFirst; # Last col in reference
$rwLast = $_[2] ? $_[2] : $rwFirst; # Last row in reference
$colLast = $_[3] ? $_[3] : $colFirst; # Last col in reference
// Swap last row/col for first row/col as necessary
if ($rwFirst > $rwLast) {

View File

@@ -19,7 +19,8 @@ for ($col=0;$col<50;$col++) {
$workbook->close();
header("Content-Type: application/x-msexcel");
header("Content-Type: application/x-msexcel; name=\"example-bigfile.xls\"");
header("Content-Disposition: inline; filename=\"example-bigfile.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);

View File

@@ -0,0 +1,115 @@
<?php
# Demonstrates Spreadsheet::WriteExcel's named colors and the Excel
# color palette.
#
# reverse('<27>'), March 2002, John McNamara, jmcnamara@cpan.org
# PHP port by Johann Hanne, 2005-11-01
set_time_limit(10);
require_once "class.writeexcel_workbook.inc.php";
require_once "class.writeexcel_worksheet.inc.php";
$fname = tempnam("/tmp", "colors.xls");
$workbook = &new writeexcel_workbook($fname);
# Some common formats
$center =& $workbook->addformat(array('align' => 'center'));
$heading =& $workbook->addformat(array('align' => 'center', 'bold' => 1));
# Try this to see the default Excel 5 palette
# $workbook->set_palette_xl5();
######################################################################
#
# Demonstrate the named colors.
#
$colors = array(
'black'=>0x08,
'blue'=>0x0C,
'brown'=>0x10,
'cyan'=>0x0F,
'gray'=>0x17,
'green'=>0x11,
'lime'=>0x0B,
'magenta'=>0x0E,
'navy'=>0x12,
'orange'=>0x35,
'purple'=>0x14,
'red'=>0x0A,
'silver'=>0x16,
'white'=>0x09,
'yellow'=>0x0D
);
$worksheet1 =& $workbook->addworksheet('Named colors');
$worksheet1->set_column(0, 3, 15);
$worksheet1->write(0, 0, "Index", $heading);
$worksheet1->write(0, 1, "Index", $heading);
$worksheet1->write(0, 2, "Name", $heading);
$worksheet1->write(0, 3, "Color", $heading);
$i = 1;
foreach ($colors as $color=>$index) {
$format =& $workbook->addformat(array(
'fg_color' => $color,
'pattern' => 1,
'border' => 1
));
$worksheet1->write($i+1, 0, $index, $center);
$worksheet1->write($i+1, 1, sprintf("0x%02X", $index), $center);
$worksheet1->write($i+1, 2, $color, $center);
$worksheet1->write($i+1, 3, '', $format);
$i++;
}
######################################################################
#
# Demonstrate the standard Excel colors in the range 8..63.
#
$worksheet2 =& $workbook->addworksheet('Standard colors');
$worksheet2->set_column(0, 3, 15);
$worksheet2->write(0, 0, "Index", $heading);
$worksheet2->write(0, 1, "Index", $heading);
$worksheet2->write(0, 2, "Color", $heading);
$worksheet2->write(0, 3, "Name", $heading);
for ($i=8;$i<=63;$i++) {
$format =& $workbook->addformat(array(
'fg_color' => $i,
'pattern' => 1,
'border' => 1
));
$worksheet2->write(($i -7), 0, $i, $center);
$worksheet2->write(($i -7), 1, sprintf("0x%02X", $i), $center);
$worksheet2->write(($i -7), 2, '', $format);
# Add the color names
foreach ($colors as $color=>$index) {
if ($i==$index) {
$worksheet2->write(($i -7), 3, $color, $center);
}
}
}
$workbook->close();
header("Content-Type: application/x-msexcel; name=\"example-colors.xls\"");
header("Content-Disposition: inline; filename=\"example-colors.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);
?>

View File

@@ -61,11 +61,9 @@ $worksheet->write('B6', 37257, $num2_format);
#
# Formulae
#
/*
$worksheet->set_selection('B7');
$worksheet->write('A7', 'Formulas and functions, "=SIN(PI()/4)"');
$worksheet->write('B7', '=SIN(PI()/4)');
*/
#######################################################################
#
@@ -90,7 +88,8 @@ $worksheet->write('A18', "Multiple worksheets");
$workbook->close();
header("Content-Type: application/x-msexcel");
header("Content-Type: application/x-msexcel; name=\"example-demo.xls\"");
header("Content-Disposition: inline; filename=\"example-demo.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);

View File

@@ -51,7 +51,8 @@ $worksheet->write_blank(2, 2, $border2);
$workbook->close();
header("Content-Type: application/x-msexcel");
header("Content-Type: application/x-msexcel; name=\"example-merge2.xls\"");
header("Content-Disposition: inline; filename=\"example-merge2.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);

View File

@@ -0,0 +1,144 @@
<?php
# Example of using the WriteExcel module to create worksheet panes.
#
# reverse('<27>'), May 2001, John McNamara, jmcnamara@cpan.org
# PHP port by Johann Hanne, 2005-11-01
set_time_limit(10);
require_once "class.writeexcel_workbook.inc.php";
require_once "class.writeexcel_worksheet.inc.php";
$fname = tempnam("/tmp", "panes.xls");
$workbook = &new writeexcel_workbook($fname);
$worksheet1 =& $workbook->addworksheet('Panes 1');
$worksheet2 =& $workbook->addworksheet('Panes 2');
$worksheet3 =& $workbook->addworksheet('Panes 3');
$worksheet4 =& $workbook->addworksheet('Panes 4');
# Frozen panes
$worksheet1->freeze_panes(1, 0); # 1 row
$worksheet2->freeze_panes(0, 1); # 1 column
$worksheet3->freeze_panes(1, 1); # 1 row and column
# Un-frozen panes. The divisions must be specified in terms of row and column
# dimensions. The default row height is 12.75 and the default column width
# is 8.43
#
$worksheet4->thaw_panes(12.75, 8.43, 1, 1); # 1 row and column
#######################################################################
#
# Set up some formatting and text to highlight the panes
#
$header =& $workbook->addformat();
$header->set_color('white');
$header->set_align('center');
$header->set_align('vcenter');
$header->set_pattern();
$header->set_fg_color('green');
$center =& $workbook->addformat();
$center->set_align('center');
#######################################################################
#
# Sheet 1
#
$worksheet1->set_column('A:I', 16);
$worksheet1->set_row(0, 20);
$worksheet1->set_selection('C3');
for ($i=0;$i<=8;$i++) {
$worksheet1->write(0, $i, 'Scroll down', $header);
}
for ($i=1;$i<=100;$i++) {
for ($j=0;$j<=8;$j++) {
$worksheet1->write($i, $j, $i+1, $center);
}
}
#######################################################################
#
# Sheet 2
#
$worksheet2->set_column('A:A', 16);
$worksheet2->set_selection('C3');
for ($i=0;$i<=49;$i++) {
$worksheet2->set_row($i, 15);
$worksheet2->write($i, 0, 'Scroll right', $header);
}
for ($i=0;$i<=49;$i++) {
for ($j=1;$j<=25;$j++) {
$worksheet2->write($i, $j, $j, $center);
}
}
#######################################################################
#
# Sheet 3
#
$worksheet3->set_column('A:Z', 16);
$worksheet3->set_selection('C3');
for ($i=1;$i<=25;$i++) {
$worksheet3->write(0, $i, 'Scroll down', $header);
}
for ($i=1;$i<=49;$i++) {
$worksheet3->write($i, 0, 'Scroll right', $header);
}
for ($i=1;$i<=49;$i++) {
for ($j=1;$j<=25;$j++) {
$worksheet3->write($i, $j, $j, $center);
}
}
#######################################################################
#
# Sheet 4
#
$worksheet4->set_selection('C3');
for ($i=1;$i<=25;$i++) {
$worksheet4->write(0, $i, 'Scroll', $center);
}
for ($i=1;$i<=49;$i++) {
$worksheet4->write($i, 0, 'Scroll', $center);
}
for ($i=1;$i<=49;$i++) {
for ($j=1;$j<=25;$j++) {
$worksheet4->write($i, $j, $j, $center);
}
}
$workbook->close();
header("Content-Type: application/x-msexcel; name=\"example-panes.xls\"");
header("Content-Disposition: inline; filename=\"example-panes.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);
?>

View File

@@ -0,0 +1,29 @@
<?php
set_time_limit(10);
require_once "class.writeexcel_workbook.inc.php";
require_once "class.writeexcel_worksheet.inc.php";
$fname = tempnam("/tmp", "repeat.xls");
$workbook = &new writeexcel_workbook($fname);
$worksheet = &$workbook->addworksheet();
$worksheet->repeat_rows(0, 1);
$worksheet->write(0, 0, "Header line (will be repeated when printed)");
$worksheet->write(1, 0, "Header line number 2");
for ($i=1;$i<=100;$i++) {
$worksheet->write($i+1, 0, "Line $i");
}
$workbook->close();
header("Content-Type: application/x-msexcel; name=\"example-repeat.xls\"");
header("Content-Disposition: inline; filename=\"example-repeat.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);
?>

View File

@@ -5,7 +5,7 @@ set_time_limit(10);
require_once "class.writeexcel_workbook.inc.php";
require_once "class.writeexcel_worksheet.inc.php";
$fname = tempnam("/tmp", "merge2.xls");
$fname = tempnam("/tmp", "simple.xls");
$workbook = &new writeexcel_workbook($fname);
$worksheet = &$workbook->addworksheet();
@@ -22,16 +22,17 @@ $worksheet->write(3, 0, 3.00000); # Writes 3
$worksheet->write(4, 0, 3.00001); # Writes 3.00001
$worksheet->write(5, 0, 3.14159); # TeX revision no.?
# Formulas are not yet supported
//$worksheet->write(7, 0, '=A3 + A6');
//$worksheet->write(8, 0, '=IF(A5>3,"Yes", "No")');
# Write two formulas
$worksheet->write(7, 0, '=A3 + A6');
$worksheet->write(8, 0, '=IF(A5>3,"Yes", "No")');
# Write a hyperlink
$worksheet->write(7, 0, 'http://www.php.net/');
$worksheet->write(10, 0, 'http://www.php.net/');
$workbook->close();
header("Content-Type: application/x-msexcel");
header("Content-Type: application/x-msexcel; name=\"example-simple.xls\"");
header("Content-Disposition: inline; filename=\"example-simple.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);

View File

@@ -5,7 +5,7 @@ set_time_limit(10);
require_once "class.writeexcel_workbook.inc.php";
require_once "class.writeexcel_worksheet.inc.php";
$fname = tempnam("/tmp", "merge2.xls");
$fname = tempnam("/tmp", "stocks.xls");
$workbook = &new writeexcel_workbook($fname);
$worksheet =& $workbook->addworksheet();
@@ -62,7 +62,8 @@ $worksheet->write(3, 3, 0, $f_change); # 0 in the font color (black)
$workbook->close();
header("Content-Type: application/x-msexcel");
header("Content-Type: application/x-msexcel; name=\"example-stocks.xls\"");
header("Content-Disposition: inline; filename=\"example-stocks.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);

View File

@@ -3,7 +3,7 @@
require_once "class.writeexcel_workbook.inc.php";
require_once "class.writeexcel_worksheet.inc.php";
$fname = tempnam("/tmp", "merge2.xls");
$fname = tempnam("/tmp", "textwrap.xls");
$workbook = &new writeexcel_workbook($fname);
$worksheet = &$workbook->addworksheet();
@@ -63,7 +63,8 @@ $worksheet->write(5, 3, $str2, $format2);
$workbook->close();
header("Content-Type: application/x-msexcel");
header("Content-Type: application/x-msexcel; name=\"example-textwrap.xls\"");
header("Content-Disposition: inline; filename=\"example-textwrap.xls\"");
$fh=fopen($fname, "rb");
fpassthru($fh);
unlink($fname);

View File

@@ -0,0 +1,120 @@
<?php
define(PpsType_Root, 5);
define(PpsType_Dir, 1);
define(PpsType_File, 2);
define(DataSizeSmall, 0x1000);
define(LongIntSize, 4);
define(PpsSize, 0x80);
function Asc2Ucs($sAsc) {
return implode("\x00", (preg_split('//', $sAsc, -1, PREG_SPLIT_NO_EMPTY)))."\x00";
}
function Ucs2Asc($sUcs) {
$chars=explode("\x00", $sUcs);
array_pop($chars);
return implode("", $chars);
}
function OLEDate2Local($sDateTime) {
/* TODO!!!
//my($iSec, $iMin, $iHour, $iDay, $iMon, $iYear);
//my($iDate);
//my($iDt, $iYDays);
#1.Divide Day and Time
my $iBigDt = Math::BigInt->new(0);
foreach my $sWk (reverse(split //, $sDateTime)) {
$iBigDt *= 0x100;
$iBigDt += ord($sWk);
}
my $iHSec = $iBigDt % 10000000;
$iBigDt /= 10000000;
my $iBigDay = int($iBigDt / (24*3600)) + 1;
my $iTime = int($iBigDt % (24*3600));
#2. Year->Day(1601/1/2?)
$iDt = $iBigDay;
$iYear = 1601;
$iYDays = _yearDays($iYear); #Not 365 (365 days is Only in Excel World)
while($iDt > $iYDays) {
$iDt -= $iYDays;
$iYear++;
$iYDays = _yearDays($iYear);
}
my $iMD;
for($iMon=1;$iMon < 12; $iMon++){
$iMD = _monthDays($iMon, $iYear);
last if($iDt <= $iMD);
$iDt -= $iMD;
}
$iDay = $iDt;
#3. Hour->iSec
$iHour = int($iTime / 3600);
$iMin = int(($iTime % 3600) / 60);
$iSec = $iTime % 60;
return ($iSec, $iMin, $iHour, $iDay, $iMon - 1, $iYear-1900, $iHSec);
*/
}
#------------------------------------------------------------------------------
# Localtime->OLE Date
#------------------------------------------------------------------------------
function LocalDate2OLE($raDate) {
/* TODO!!!
if (!$raDate) {
return str_repeat("\x00", 8);
}
list($iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iHSec) = $raDate;
$iSec ||=0; $iMin ||=0; $iHour ||=0;
$iDay ||=0; $iMon ||=0; $iYear ||=0; $iHSec ||=0;
//my($iDate);
//my($iDt, $iYDays);
#1. Year -> Days
$iDate = -1;
for ($iY=1601;$iY<($iYear+1900);$iY++){
$iDate += _yearDays($iY);
}
for ($iM=0;$iM < $iMon;$iM++){
$iDate += _monthDays($iM+1, ($iYear+1900));
}
$iDate += $iDay;
#2. Hours->Sec + HighReso
my $iBigDt = Math::BigInt->new(0);
$iBigDt += $iHour*3600 + $iMin*60+ $iSec;
$iBigDt += ($iDate*(24*3600));
$iBigDt *= 10000000;
$iBigDt += $iHSec if($iHSec);
#3. Make HEX string
//my $iHex;
$sRes = '';
for($i=0;$i<8;$i++) {
$iHex = $iBigDt % 0x100;
$sRes .= pack('c', $iHex);
$iBigDt /= 0x100;
}
return $sRes;
*/
}
function _leapYear($iYear) {
return ((($iYear % 4)==0) && (($iYear % 100) || ($iYear % 400)==0)) ? 1 : 0;
}
function _yearDays($iYear) {
return _leapYear($iYear) ? 366 : 365;
}
function _monthDays($iMon, $iYear) {
if ($iMon == 1 || $iMon == 3 || $iMon == 5 || $iMon == 7 ||
$iMon == 8 || $iMon == 10 || $iMon == 12) {
return 31;
} elseif ($iMon == 4 || $iMon == 6 || $iMon == 9 || $iMon == 11) {
return 30;
} elseif ($iMon == 2) {
return _leapYear($iYear) ? 29 : 28;
}
}
?>