From 95da6b5c055092c51ca92aabdf71e7e049a2e95e Mon Sep 17 00:00:00 2001 From: Javier Date: Sun, 2 Apr 2023 19:03:38 -0300 Subject: [PATCH] Update SimpleXLSXGen.php --- src/SimpleXLSXGen.php | 135 +++++++++++++----------------------------- 1 file changed, 41 insertions(+), 94 deletions(-) diff --git a/src/SimpleXLSXGen.php b/src/SimpleXLSXGen.php index 8820e58..e0c3444 100644 --- a/src/SimpleXLSXGen.php +++ b/src/SimpleXLSXGen.php @@ -13,7 +13,6 @@ namespace Shuchkin; */ class SimpleXLSXGen { - public $curSheet; protected $defaultFont; protected $defaultFontSize; @@ -111,7 +110,6 @@ class SimpleXLSXGen self::B_SLANT_DASH_DOT => 'slantDashDot' ]; - $this->XF = [ // styles 0 - num fmt, 1 - align, 2 - font, 3 - fill, 4 - font color, 5 - bgcolor, 6 - border, 7 - font size [self::N_NORMAL, self::A_DEFAULT, self::F_NORMAL, self::FL_NONE, 0, 0, '', 0], [self::N_NORMAL, self::A_DEFAULT, self::F_NORMAL, self::FL_GRAY_125, 0, 0, '', 0], // hack @@ -119,7 +117,6 @@ class SimpleXLSXGen $this->XF_KEYS[implode('-', $this->XF[0])] = 0; // & keys $this->XF_KEYS[implode('-', $this->XF[1])] = 1; - $this->template = [ '_rels/.rels' => ' @@ -130,7 +127,8 @@ class SimpleXLSXGen 'docProps/app.xml' => ' 0 -' . __CLASS__ . '', +' . __CLASS__ . ' +', 'docProps/core.xml' => ' {DATE} @@ -143,9 +141,13 @@ class SimpleXLSXGen {SHEETS}', 'xl/worksheets/sheet1.xml' => ' -{COLS}{ROWS}{AUTOFILTER}{MERGECELLS}{HYPERLINKS}', + + +{SHEETVIEWS} +{COLS} +{ROWS} +{AUTOFILTER}{MERGECELLS}{HYPERLINKS} +', 'xl/worksheets/_rels/sheet1.xml.rels' => ' {HYPERLINKS}', 'xl/sharedStrings.xml' => ' @@ -158,15 +160,15 @@ class SimpleXLSXGen {BORDERS} {XF} - - - + ', 'xl/workbook.xml' => ' - + + {SHEETS} -', + +', '[Content_Types].xml' => ' @@ -179,7 +181,6 @@ class SimpleXLSXGen {TYPES} ', ]; - // // 01001200 // Простой шаблонБудем делать генератор @@ -192,7 +193,6 @@ class SimpleXLSXGen public function addSheet(array $rows, $name = null) { - $this->curSheet++; if ($name === null) { // autogenerated sheet names $name = 'Sheet' . ($this->curSheet + 1); @@ -215,9 +215,7 @@ class SimpleXLSXGen } } } - $this->sheets[$this->curSheet] = ['name' => $name, 'hyperlinks' => [], 'mergecells' => [], 'colwidth' => [], 'autofilter' => '', 'frozen' => '']; - if (isset($rows[0]) && is_array($rows[0])) { $this->sheets[$this->curSheet]['rows'] = $rows; } else { @@ -232,14 +230,12 @@ class SimpleXLSXGen if (!$fh) { return ''; } - if (!$this->_write($fh)) { fclose($fh); return ''; } $size = ftell($fh); fseek($fh, 0); - return (string)fread($fh, $size); } @@ -254,7 +250,6 @@ class SimpleXLSXGen return false; } fclose($fh); - return true; } @@ -269,44 +264,34 @@ class SimpleXLSXGen if (!$fh) { return false; } - if (!$this->_write($fh)) { fclose($fh); return false; } - $size = ftell($fh); - header('Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment; filename="' . $filename . '"'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time())); header('Content-Length: ' . $size); - while (ob_get_level()) { ob_end_clean(); } fseek($fh, 0); fpassthru($fh); - fclose($fh); return true; } protected function _write($fh) { - - $dirSignatureE = "\x50\x4b\x05\x06"; // end of central dir signature $zipComments = 'Generated by ' . __CLASS__ . ' PHP class, thanks sergey.shuchkin@gmail.com'; - if (!$fh) { return false; } - $cdrec = ''; // central directory content $entries = 0; // number of zipped files $cnt_sheets = count($this->sheets); - foreach ($this->template as $cfilename => $template) { if ($cfilename === 'xl/_rels/workbook.xml.rels') { $s = ''; @@ -363,12 +348,10 @@ class SimpleXLSXGen } } $xml = null; - } elseif ($cfilename === '[Content_Types].xml') { $TYPES = ['']; foreach ($this->sheets as $k => $v) { - $TYPES[] = ''; + $TYPES[] = ''; if ($this->extLinkId) { $TYPES[] = ''; } @@ -380,20 +363,17 @@ class SimpleXLSXGen $NF = $XF = $FONTS = $F_KEYS = $FILLS = $FL_KEYS = []; $BR = ['']; $BR_KEYS = [0 => 0]; - foreach ($this->NF as $k => $v) { $NF[] = ''; } - foreach ($this->XF as $xf) { // 0 - num fmt, 1 - align, 2 - font, 3 - fill, 4 - font color, 5 - bgcolor, 6 - border, 7 - font size // fonts - $F_KEY = $xf[2] . '-' . $xf[4].'-'.$xf[7]; + $F_KEY = $xf[2] . '-' . $xf[4] . '-' . $xf[7]; if (isset($F_KEYS[$F_KEY])) { $F_ID = $F_KEYS[$F_KEY]; } else { $F_ID = $F_KEYS[$F_KEY] = count($FONTS); - $FONTS[] = '' . ($xf[7] ? '' : '') . ($xf[2] & self::F_BOLD ? '' : '') @@ -428,7 +408,6 @@ class SimpleXLSXGen . ($xf[1] & self::A_MIDDLE ? ' vertical="center"' : '') . ($xf[1] & self::A_BOTTOM ? ' vertical="bottom"' : '') . ($xf[1] & self::A_WRAPTEXT ? ' wrapText="1"' : ''); - // border $BR_ID = 0; if ($xf[6] !== '') { @@ -452,7 +431,6 @@ class SimpleXLSXGen foreach ($sides as $side => $idx) { $s = 'thin'; $c = ''; - $va = explode('#', $ba[$idx]); if (isset($va[1])) { $s = $va[0] === '' ? 'thin' : $va[0]; @@ -465,7 +443,6 @@ class SimpleXLSXGen if (strlen($c) === 6) { $c = 'FF' . $c; } - if ($s && $s !== 'none') { $border .= '<' . $side . ' style="' . $s . '">' . '' @@ -473,24 +450,18 @@ class SimpleXLSXGen } else { $border .= '<' . $side . '/>'; } - } $border .= ''; $BR[] = $border; } } - - $XF[] = ' 0 ? ' applyNumberFormat="1"' : '') . ($F_ID > 0 ? ' applyFont="1"' : '') . ($FL_ID > 0 ? ' applyFill="1"' : '') . ($BR_ID > 0 ? ' applyBorder="1"' : '') . ($align ? ' applyAlignment="1">' : '/>'); - } - - // wrap collections array_unshift($NF, ''); $NF[] = ''; @@ -506,7 +477,8 @@ class SimpleXLSXGen $template = str_replace( ['{NUMFMTS}', '{FONTS}', '{XF}', '{FILLS}', '{BORDERS}'], [implode("\r\n", $NF), implode("\r\n", $FONTS), implode("\r\n", $XF), implode("\r\n", $FILLS), implode("\r\n", $BR)], - $template); + $template + ); $this->_writeEntry($fh, $cdrec, $cfilename, $template); $entries++; } else { @@ -516,7 +488,6 @@ class SimpleXLSXGen } $before_cd = ftell($fh); fwrite($fh, $cdrec); - // end of central dir fwrite($fh, $dirSignatureE); fwrite($fh, pack('v', 0)); // number of this disk @@ -527,7 +498,6 @@ class SimpleXLSXGen fwrite($fh, pack('V', $before_cd)); // offset to start of central dir fwrite($fh, pack('v', mb_strlen($zipComments, '8bit'))); // .zip file comment length fwrite($fh, $zipComments); - return true; } @@ -538,7 +508,6 @@ class SimpleXLSXGen $e = []; $e['uncsize'] = mb_strlen($data, '8bit'); - // if data to compress is too small, just store it if ($e['uncsize'] < 256) { $e['comsize'] = $e['uncsize']; @@ -552,7 +521,6 @@ class SimpleXLSXGen $e['vneeded'] = 10; $e['cmethod'] = 8; } - $e['bitflag'] = 0; $e['crc_32'] = crc32($data); @@ -566,7 +534,6 @@ class SimpleXLSXGen $e['modtime'] = bindec("$lastmod_timeH$lastmod_timeM$lastmod_timeS"); $e['moddate'] = bindec("$lastmod_dateY$lastmod_dateM$lastmod_dateD"); - $e['offset'] = ftell($fh); fwrite($fh, $zipSignature); @@ -589,22 +556,22 @@ class SimpleXLSXGen $e['comments'] = ''; $cdrec .= $dirSignature; - $cdrec .= "\x0\x0"; // version made by - $cdrec .= pack('v', $e['vneeded']); // version needed to extract - $cdrec .= "\x0\x0"; // general bit flag - $cdrec .= pack('v', $e['cmethod']); // compression method - $cdrec .= pack('v', $e['modtime']); // lastmod time - $cdrec .= pack('v', $e['moddate']); // lastmod date - $cdrec .= pack('V', $e['crc_32']); // crc32 - $cdrec .= pack('V', $e['comsize']); // compressed filesize - $cdrec .= pack('V', $e['uncsize']); // uncompressed filesize - $cdrec .= pack('v', mb_strlen($cfilename, '8bit')); // file name length - $cdrec .= pack('v', 0); // extra field length + $cdrec .= "\x0\x0"; // version made by + $cdrec .= pack('v', $e['vneeded']); // version needed to extract + $cdrec .= "\x0\x0"; // general bit flag + $cdrec .= pack('v', $e['cmethod']); // compression method + $cdrec .= pack('v', $e['modtime']); // lastmod time + $cdrec .= pack('v', $e['moddate']); // lastmod date + $cdrec .= pack('V', $e['crc_32']); // crc32 + $cdrec .= pack('V', $e['comsize']); // compressed filesize + $cdrec .= pack('V', $e['uncsize']); // uncompressed filesize + $cdrec .= pack('v', mb_strlen($cfilename, '8bit')); // file name length + $cdrec .= pack('v', 0); // extra field length $cdrec .= pack('v', mb_strlen($e['comments'], '8bit')); // file comment length - $cdrec .= pack('v', 0); // disk number start - $cdrec .= pack('v', 0); // internal file attributes - $cdrec .= pack('V', $e['external_attributes']); // internal file attributes - $cdrec .= pack('V', $e['offset']); // relative offset of local header + $cdrec .= pack('v', 0); // disk number start + $cdrec .= pack('v', 0); // internal file attributes + $cdrec .= pack('V', $e['external_attributes']); // internal file attributes + $cdrec .= pack('V', $e['offset']); // relative offset of local header $cdrec .= $cfilename; $cdrec .= $e['comments']; } @@ -635,19 +602,19 @@ class SimpleXLSXGen if ($x > 0 || $y > 0) { $split = ''; if ($x > 0) { - $split .= ' xSplit="'.$x.'"'; + $split .= ' xSplit="' . $x . '"'; } if ($y > 0) { - $split .= ' ySplit="'.$y.'"'; + $split .= ' ySplit="' . $y . '"'; } $activepane = 'bottomRight'; - if ($x > 0 && $y === 0) { + if ($x > 0 && $y === 0) { $activepane = 'topRight'; } - if ($x === 0 && $y > 0) { + if ($x === 0 && $y > 0) { $activepane = 'bottomLeft'; } - $SHEETVIEWS = ''; + $SHEETVIEWS = ''; } } $COLS[] = ''; @@ -664,18 +631,14 @@ class SimpleXLSXGen $COL[$CUR_COL] = 0; } $cname = $this->num2name($CUR_COL) . $CUR_ROW; - if ($v === null || $v === '') { $row .= ''; continue; } - $ct = $cv = $cf = null; $N = $A = $F = $FL = $C = $BG = $FS = 0; $BR = ''; - if (is_string($v)) { - if ($v[0] === "\0") { // RAW value as string $v = substr($v, 1); $vl = mb_strlen($v); @@ -694,9 +657,7 @@ class SimpleXLSXGen $F += self::F_STRIKE; } if (preg_match('/]+)>/', $v, $m)) { - if (preg_match('/ color="([^"]+)"/', $m[1], $m2)) { - $F += self::F_COLOR; $c = ltrim($m2[1], '#'); $C = strlen($c) === 8 ? $c : ('FF' . $c); @@ -834,9 +795,7 @@ class SimpleXLSXGen } } if ($cv === null) { - $v = $this->esc($v); - if ($cf) { $ct = 'str'; $cv = $v; @@ -870,13 +829,9 @@ class SimpleXLSXGen } else { continue; } - $COL[$CUR_COL] = max($vl, $COL[$CUR_COL]); - $cs = 0; - if (($N + $A + $F + $FL + $FS > 0) || $BR !== '') { - if ($FL === self::FL_COLOR) { $FL += self::FL_SOLID; } @@ -884,7 +839,6 @@ class SimpleXLSXGen $F += self::F_COLOR; $C = 'FF0563C1'; } - $XF_KEY = $N . '-' . $A . '-' . $F . '-' . $FL . '-' . $C . '-' . $BG . '-' . $BR . '-' . $FS; if (isset($this->XF_KEYS[$XF_KEY])) { $cs = $this->XF_KEYS[$XF_KEY]; @@ -895,7 +849,6 @@ class SimpleXLSXGen $this->XF[] = [$N, $A, $F, $FL, $C, $BG, $BR, $FS]; } } - $row .= '' . ($cf ? '' . $cf . '' : '') . ($ct === 'inlineStr' ? '' . $cv . '' : '' . $cv . '') . "\r\n"; @@ -966,20 +919,16 @@ class SimpleXLSXGen public function date2excel($year, $month, $day, $hours = 0, $minutes = 0, $seconds = 0) { - $excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400; - if ((int)$year === 0) { return $excelTime; } - // self::CALENDAR_WINDOWS_1900 $excel1900isLeapYear = True; if (($year === 1900) && ($month <= 2)) { $excel1900isLeapYear = False; } $myExcelBaseDate = 2415020; - // Julian base date Adjustment if ($month > 2) { $month -= 3; @@ -991,7 +940,6 @@ class SimpleXLSXGen $decade = substr($year, 2, 2); // Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0) $excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $myExcelBaseDate + $excel1900isLeapYear; - return (float)$excelDate + $excelTime; } @@ -1078,13 +1026,13 @@ class SimpleXLSXGen } } - public static function coord2cell($x, $y, $absolute = false) + public static function coord2cell($x, $y) { $c = ''; for ($i = $x; $i >= 0; $i = ((int)($i / 26)) - 1) { $c = chr(ord('A') + $i % 26) . $c; } - return ($absolute ? '$' : '') . $c . $absolute . ($y+1); + return $c . ($y+1); } public function freezePanes($cell) @@ -1092,5 +1040,4 @@ class SimpleXLSXGen $this->sheets[$this->curSheet]['frozen'] = $cell; return $this; } - -} +} \ No newline at end of file