From 366a3ecbcd7841413f980f9e1d65895b77af1b82 Mon Sep 17 00:00:00 2001 From: Joe Hunt Date: Thu, 8 Jun 2017 08:32:44 +0200 Subject: [PATCH] Fixed more rows when reporting to Excel Reports. Greater then 65535 rows. --- reporting/includes/Workbook.php | 1138 ++++++++++++++++++--------- reporting/includes/excel_report.inc | 14 +- 2 files changed, 790 insertions(+), 362 deletions(-) diff --git a/reporting/includes/Workbook.php b/reporting/includes/Workbook.php index 718bdb66..30a716cb 100644 --- a/reporting/includes/Workbook.php +++ b/reporting/includes/Workbook.php @@ -102,382 +102,795 @@ define('SPREADSHEET_EXCEL_WRITER_EQ', "="); */ define('SPREADSHEET_EXCEL_WRITER_NE', "<>"); -/** -* Class for creating OLE streams for Excel Spreadsheets -* -* @author Xavier Noguer -* @package Spreadsheet_WriteExcel -*/ -class OLEwriter +define('PpsType_Root', 5); +define('PpsType_Dir', 1); +define('PpsType_File', 2); +define('DataSizeSmall', 0x1000); +define('LongIntSize', 4); +define('PpsSize', 0x80); + +function Asc2Ucs($sAsc) { - /** - * Filename for the OLE stream - * @var string - * @see _initialize() - */ - var $_OLEfilename; + return implode("\x00", (preg_split('//', $sAsc, -1, PREG_SPLIT_NO_EMPTY)))."\x00"; +} - /** - * Filehandle for the OLE stream - * @var resource - */ - var $_filehandle; +function Ucs2Asc($sUcs) +{ + $chars=explode("\x00", $sUcs); + array_pop($chars); + return implode("", $chars); +} - /** - * Name of the temporal file in case OLE stream goes to stdout - * @var string - */ - var $_tmp_filename; +function OLEDate2Local($sDateTime) +{ +} - /** - * Variable for preventing closing two times - * @var integer - */ - var $_fileclosed; +#------------------------------------------------------------------------------ +# Localtime->OLE Date +#------------------------------------------------------------------------------ +function LocalDate2OLE($raDate) +{ +} - /** - * Size of the data to be written to the OLE stream - * @var integer - */ - var $_biffsize; +function _leapYear($iYear) +{ + return ((($iYear % 4)==0) && (($iYear % 100) || ($iYear % 400)==0)) ? 1 : 0; +} - /** - * Real data size to be written to the OLE stream - * @var integer - */ - var $_booksize; +function _yearDays($iYear) +{ + return _leapYear($iYear) ? 366 : 365; +} - /** - * Number of big blocks in the OLE stream - * @var integer - */ - var $_big_blocks; +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; +} - /** - * Number of list blocks in the OLE stream - * @var integer - */ - var $_list_blocks; +/* + * This is the OLE::Storage_Lite Perl package ported to PHP + * OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org + */ - /** - * Number of big blocks in the OLE stream - * @var integer - */ - var $_root_start; +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; + var $_PPS_FILE; + + #------------------------------------------------------------------------------ + # _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; + $this->_PPS_FILE = NULL; + } + + #------------------------------------------------------------------------------ + # _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; + $sRes = ''; + + for ($c=0;$c_OLEfilename = $OLEfilename; - $this->_filehandle = ''; - $this->_tmp_filename = ''; - $this->_fileclosed = 0; - $this->_biff_only = 0; - //$this->_size_allowed = 0; - $this->_biffsize = 0; - $this->_booksize = 0; - $this->_big_blocks = 0; - $this->_list_blocks = 0; - $this->_root_start = 0; - //$this->_block_count = 4; - $this->_initialize(); - } + #1. Make SBD, small data string - /** - * Check for a valid filename and store the filehandle. - * Filehandle "-" writes to STDOUT - * - * @access private - */ - function _initialize() - { - $OLEfile = $this->_OLEfilename; + if ($oPps->Type==PpsType_File) + { + if ($oPps->Size<=0) + continue; - if (($OLEfile == '-') or ($OLEfile == '')) { - $this->_tmp_filename = tempnam("/tmp", "OLEwriter"); - $fh = fopen($this->_tmp_filename, "wb"); - if ($fh == false) { - die("Can't create temporary file."); - } - } else { - // Create a new file, open for writing (in binmode) - $fh = fopen($OLEfile, "wb"); - if ($fh == false) { - die("Can't open $OLEfile. It may be in use or protected."); + 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; + } } - } - - // Store filehandle - $this->_filehandle = $fh; - } - - - /** - * Set the size of the data to be written to the OLE stream. - * The maximun size comes from this: - * $big_blocks = (109 depot block x (128 -1 marker word) - * - (1 x end words)) = 13842 - * $maxsize = $big_blocks * 512 bytes = 7087104 - * - * @access public - * @see Spreadsheet_Excel_Writer_Workbook::store_OLE_file() - * @param integer $biffsize The size of the data to be written to the OLE stream - * @return integer 1 for success - */ - function setSize($biffsize) - { - $maxsize = 7087104; // TODO: extend max size - if ($biffsize > $maxsize) { - die("Maximum file size, $maxsize, exceeded."); } - - $this->_biffsize = $biffsize; - // Set the min file size to 4k to avoid having to use small blocks - if ($biffsize > 4096) { - $this->_booksize = $biffsize; - } else { - $this->_booksize = 4096; - } - //$this->_size_allowed = 1; - return(1); + $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 + "\x00\x00\x00\x00\x00\x00\x00\x00". + "\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 + ); } +} - /** - * Calculate various sizes needed for the OLE stream - * - * @access private - */ - function _calculateSizes() - { - $datasize = $this->_booksize; - if ($datasize % 512 == 0) { - $this->_big_blocks = $datasize/512; - } else { - $this->_big_blocks = floor($datasize/512) + 1; - } - // There are 127 list blocks and 1 marker blocks for each big block - // depot + 1 end of chain block - $this->_list_blocks = floor(($this->_big_blocks)/127) + 1; - $this->_root_start = $this->_big_blocks; - } +/* + * This is the OLE::Storage_Lite Perl package ported to PHP + * OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org + */ - /** - * Write root entry, big block list and close the filehandle. - * This routine is used to explicitly close the open filehandle without - * having to wait for DESTROY. - * - * @access public - * @see Spreadsheet_Excel_Writer_Workbook::store_OLE_file() - */ - function close() - { - //return if not $this->{_size_allowed}; - $this->_writePadding(); - $this->_writePropertyStorage(); - $this->_writeBigBlockDepot(); - // Close the filehandle - fclose($this->_filehandle); - if (($this->_OLEfilename == '-') or ($this->_OLEfilename == '')) { - $fh = fopen($this->_tmp_filename, "rb"); - if ($fh == false) { - die("Can't read temporary file."); +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"); } - fpassthru($fh); - @unlink($this->_tmp_filename); - } - $this->_fileclosed = 1; - } - - - /** - * Write BIFF data to OLE file. - * - * @param string $data string of bytes to be written - */ - function write($data) - { - fwrite($this->_filehandle, $data, strlen($data)); - } - - - /** - * Write OLE header block. - */ - function writeHeader() - { - $this->_calculateSizes(); - $root_start = $this->_root_start; - $num_lists = $this->_list_blocks; - $id = pack("nnnn", 0xD0CF, 0x11E0, 0xA1B1, 0x1AE1); - $unknown1 = pack("VVVV", 0x00, 0x00, 0x00, 0x00); - $unknown2 = pack("vv", 0x3E, 0x03); - $unknown3 = pack("v", -2); - $unknown4 = pack("v", 0x09); - $unknown5 = pack("VVV", 0x06, 0x00, 0x00); - $num_bbd_blocks = pack("V", $num_lists); - $root_startblock = pack("V", $root_start); - $unknown6 = pack("VV", 0x00, 0x1000); - $sbd_startblock = pack("V", -2); - $unknown7 = pack("VVV", 0x00, -2 ,0x00); - $unused = pack("V", -1); - - fwrite($this->_filehandle, $id); - fwrite($this->_filehandle, $unknown1); - fwrite($this->_filehandle, $unknown2); - fwrite($this->_filehandle, $unknown3); - fwrite($this->_filehandle, $unknown4); - fwrite($this->_filehandle, $unknown5); - fwrite($this->_filehandle, $num_bbd_blocks); - fwrite($this->_filehandle, $root_startblock); - fwrite($this->_filehandle, $unknown6); - fwrite($this->_filehandle, $sbd_startblock); - fwrite($this->_filehandle, $unknown7); - - for ($i=1; $i <= $num_lists; $i++) { - $root_start++; - fwrite($this->_filehandle, pack("V",$root_start)); - } - for ($i = $num_lists; $i <=108; $i++) { - fwrite($this->_filehandle, $unused); - } - } - - - /** - * Write big block depot. - * - * @access private - */ - function _writeBigBlockDepot() - { - $num_blocks = $this->_big_blocks; - $num_lists = $this->_list_blocks; - $total_blocks = $num_lists *128; - $used_blocks = $num_blocks + $num_lists +2; - - $marker = pack("V", -3); - $end_of_chain = pack("V", -2); - $unused = pack("V", -1); - - for ($i = 1; $i < $num_blocks; $i++) { - fwrite($this->_filehandle, pack("V",$i)); - } - - fwrite($this->_filehandle, $end_of_chain); - fwrite($this->_filehandle, $end_of_chain); - for ($i = 0; $i < $num_lists; $i++) { - fwrite($this->_filehandle, $marker); - } - for ($i = $used_blocks; $i <= $total_blocks; $i++) { - fwrite($this->_filehandle, $unused); + if ($sData!==false) + fputs($this->_PPS_FILE, $sData); } } - /** - * Write property storage. TODO: add summary sheets - * - * @access private - */ - function _writePropertyStorage() + function append ($sData) { - //$rootsize = -2; - /*************** name type dir start size */ - $this->_writePps("Root Entry", 0x05, 1, -2, 0x00); - $this->_writePps("Book", 0x02, -1, 0x00, $this->_booksize); - $this->_writePps('', 0x00, -1, 0x00, 0x0000); - $this->_writePps('', 0x00, -1, 0x00, 0x0000); + if ($this->_PPS_FILE) + fputs($this->_PPS_FILE, $sData); + else + $this->Data.=$sData; } +} -/** -* Write property sheet in property storage -* -* @param string $name name of the property storage. -* @param integer $type type of the property storage. -* @param integer $dir dir of the property storage. -* @param integer $start start of the property storage. -* @param integer $size size of the property storage. -* @access private -*/ - function _writePps($name, $type, $dir, $start, $size) - { - $length = 0; - $rawname = ''; - - if ($name != '') { - $name = $name . "\0"; - $name_length = strlen($name); - for ($i = 0; $i < $name_length; $i++) { - // Simulate a Unicode string - $rawname .= pack("H*",dechex(ord($name{$i}))).pack("C",0); - } - $length = strlen($name) * 2; - } - - $zero = pack("C", 0); - $pps_sizeofname = pack("v", $length); // 0x40 - $pps_type = pack("v", $type); // 0x42 - $pps_prev = pack("V", -1); // 0x44 - $pps_next = pack("V", -1); // 0x48 - $pps_dir = pack("V", $dir); // 0x4c - - $unknown1 = pack("V", 0); - - $pps_ts1s = pack("V", 0); // 0x64 - $pps_ts1d = pack("V", 0); // 0x68 - $pps_ts2s = pack("V", 0); // 0x6c - $pps_ts2d = pack("V", 0); // 0x70 - $pps_sb = pack("V", $start); // 0x74 - $pps_size = pack("V", $size); // 0x78 - - - fwrite($this->_filehandle, $rawname); - for ($i = 0; $i < (64 -$length); $i++) { - fwrite($this->_filehandle, $zero); - } - fwrite($this->_filehandle, $pps_sizeofname); - fwrite($this->_filehandle, $pps_type); - fwrite($this->_filehandle, $pps_prev); - fwrite($this->_filehandle, $pps_next); - fwrite($this->_filehandle, $pps_dir); - for ($i = 0; $i < 5; $i++) { - fwrite($this->_filehandle, $unknown1); - } - fwrite($this->_filehandle, $pps_ts1s); - fwrite($this->_filehandle, $pps_ts1d); - fwrite($this->_filehandle, $pps_ts2d); - fwrite($this->_filehandle, $pps_ts2d); - fwrite($this->_filehandle, $pps_sb); - fwrite($this->_filehandle, $pps_size); - fwrite($this->_filehandle, $unknown1); - } +/* + * This is the OLE::Storage_Lite Perl package ported to PHP + * OLE::Storage_Lite was written by Kawai Takanori, kwitknr@cpan.org + */ - /** - * Pad the end of the file - * - * @access private - */ - function _writePadding() - { - $biffsize = $this->_biffsize; - if ($biffsize < 4096) { - $min_size = 4096; - } else { - $min_size = 512; - } - if ($biffsize % $min_size != 0) { - $padding = $min_size - ($biffsize % $min_size); - for ($i = 0; $i < $padding; $i++) { - fwrite($this->_filehandle, "\0"); - } - } - } +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 stdClass(); + + $rhInfo->_BIG_BLOCK_SIZE = $rhInfo->_SMALL_BLOCK_SIZE = 0; + $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;$cType==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;$cType!=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_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)."
\n"; + //print "yyy name: ".$aThis[0]->Name."
\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)); + } + } } /** @@ -7399,21 +7812,24 @@ class Spreadsheet_Excel_Writer_Workbook extends Spreadsheet_Excel_Writer_BIFFwri */ function _storeOLEFile() { - $OLE = new OLEwriter($this->_filename); - // Write Worksheet data if data <~ 7MB - if ($OLE->setSize($this->_biffsize)) - { - $OLE->writeHeader(); - $OLE->write($this->_data); - foreach($this->_worksheets as $sheet) - { - while ($tmp = $sheet->getData()) { - $OLE->write($tmp); - } + if($this->_BIFF_version == 0x0600) { + $OLE = new ole_pps_file(Asc2Ucs('Workbook')); + } else { + $OLE = new ole_pps_file(Asc2Ucs('Book')); + } + + $OLE->append($this->_data); + + $total_worksheets = count($this->_worksheets); + for ($i = 0; $i < $total_worksheets; $i++) { + while ($tmp = $this->_worksheets[$i]->getData()) { + $OLE->append($tmp); } } - $OLE->close(); - return true; + + $root = new ole_pps_root(false, false, array($OLE)); + + $root->save($this->_filename); } /** diff --git a/reporting/includes/excel_report.inc b/reporting/includes/excel_report.inc index c6f0d443..3786a91a 100644 --- a/reporting/includes/excel_report.inc +++ b/reporting/includes/excel_report.inc @@ -13,6 +13,7 @@ include_once($path_to_root . "/reporting/includes/Workbook.php"); include_once($path_to_root . "/admin/db/company_db.inc"); include_once($path_to_root . "/admin/db/fiscalyears_db.inc"); include_once($path_to_root . "/config.php"); +define('MAX_ROW_SHEET', 65530); // xls version class FrontReport extends Spreadsheet_Excel_Writer_Workbook { @@ -86,7 +87,7 @@ class FrontReport extends Spreadsheet_Excel_Writer_Workbook $this->Spreadsheet_Excel_Writer_Workbook($this->path."/".$this->unique_name); if ($this->code != "iso-8859-1") $this->setVersion(8); // set biff version to 8 (0x0006 internal) - $this->sheet =& $this->addWorksheet($this->worksheetNameGenerator($this->title)); + $this->sheet = $this->addWorksheet($this->worksheetNameGenerator($this->title)); if ($this->code != "iso-8859-1") $this->sheet->setInputEncoding($this->code); // set sheet encoding if ($rtl) @@ -641,6 +642,17 @@ class FrontReport extends Spreadsheet_Excel_Writer_Workbook function NewLine($l=1, $np=0, $h=NULL) { $this->y += $l; + if ($this->y > MAX_ROW_SHEET) + { + $this->y = 0; + $this->sheet = $this->addWorksheet(); + if ($this->code != "iso-8859-1") + $this->sheet->setInputEncoding($this->code); // set sheet encoding + if ($_SESSION['language']->dir == 'rtl') + $this->sheet->setRTL(); + for ($i = 0; $i < $this->numcols; $i++) + $this->sheet->setColumn($i, $i, $this->px2units($this->cols[$i + 1] - $this->cols[$i])); + } } function NewPage() -- 2.30.2