From 402c6b9417eb5e4b14268583341aa3e32b130ce3 Mon Sep 17 00:00:00 2001 From: Sergey Shuchkin Date: Sun, 24 Apr 2022 14:59:15 +0600 Subject: [PATCH] 1.2.10 --- CHANGELOG.md | 5 +- README.md | 12 +-- src/SimpleXLSXGen.php | 168 +++++++++++++++++++++++++----------------- 3 files changed, 109 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de7fbcc..786acbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # Changelog +# 1.2.10 (2022-04-24) +* Added colors `<style color="#FFFF00" bgcolor="#00FF00">Yellow text on blue background</style>`, thx [mrjemson](https://github.com/mrjemson) + # 1.1.12 (2022-03-15) -* Added $xlsx->mergeCells('A1:C1') +* Added `$xlsx->mergeCells('A1:C1')` ## 1.1.11 (2022-02-05) * sheet name maximum length is 31 chars, mb_substr used now diff --git a/README.md b/README.md index 42411c8..4a0f4f7 100644 --- a/README.md +++ b/README.md @@ -60,22 +60,22 @@ $data = [ ['Italic', '12345.67'], ['Underline', '12345.67'], ['Strike', '12345.67'], - ['Green', ''], - ['Bold Red Text', ''], - ['Blue Text and Yellow Fill', ''], ['Bold + Italic', '12345.67'], ['Hyperlink', 'https://github.com/shuchkin/simplexlsxgen'], ['Italic + Hyperlink + Anchor', 'SimpleXLSXGen'], + ['Green', ''], + ['Bold Red Text', ''], + ['Blue Text and Yellow Fill', ''], ['Left', '12345.67'], ['Center', '
12345.67
'], ['Right', 'Right Text'], ['Center + Bold', '
Name
'], - ['
MERGE CELLS
'] + ['
MERGE CELLS
', null] ]; -Shuchkin\SimpleXLSXGen::fromArray( $data ) +SimpleXLSXGen::fromArray( $data ) ->setDefaultFont( 'Courier New' ) ->setDefaultFontSize( 14 ) - ->mergeCells('A13:B13') + ->mergeCells('A16:B16') ->saveAs('styles_and_tags.xlsx'); ``` ![XLSX screenshot](styles.png) diff --git a/src/SimpleXLSXGen.php b/src/SimpleXLSXGen.php index 762b64f..247f24f 100644 --- a/src/SimpleXLSXGen.php +++ b/src/SimpleXLSXGen.php @@ -1,4 +1,9 @@ -sheets = [ ['name' => 'Sheet1', 'rows' => [], 'hyperlinks' => [], 'mergecells' => [] ] ]; $this->SI = []; // sharedStrings index $this->SI_KEYS = []; // & keys - $this->F = [ self::F_NORMAL ]; // fonts - $this->F_KEYS = [0]; // & keys - $this->C = [ self::C_NORMAL ]; // - $this->B = [ self::B_NORMAL ]; // - $this->XF = [ [self::N_NORMAL, self::F_NORMAL, self::A_DEFAULT, self::C_NORMAL, self::B_NORMAL] ]; // styles - $this->XF_KEYS = ['N0F0A0C0B0' => 0 ]; // & keys + $this->XF = [ // styles + [self::N_NORMAL, self::A_DEFAULT, self::F_NORMAL, self::FL_NONE, 0, 0], + [self::N_NORMAL, self::A_DEFAULT, self::F_NORMAL, self::FL_GRAY_125, 0, 0], // hack + ]; + $this->XF_KEYS['0-0-0-0-0-0'] = 0; // & keys + $this->XF_KEYS['0-0-0-16-0-0'] = 1; $this->template = [ '_rels/.rels' => ' @@ -299,39 +308,63 @@ class SimpleXLSXGen { $this->_writeEntry($fh, $cdrec, $cfilename, $template); $entries++; } elseif ( $cfilename === 'xl/styles.xml' ) { - $FONTS = ['']; - foreach ( $this->F as $index => $f ) { - $FONTS[] = '' - . ( $this->defaultFontSize ? '' : '' ) - .( $f & self::F_BOLD ? '' : '') - .( $f & self::F_ITALIC ? '' : '') - .( $f & self::F_UNDERLINE ? '' : '') - .( $f & self::F_STRIKE ? '' : '') - .( $f & self::F_HYPERLINK ? '' : '') - .( isset($this->C[$index]) ? '' : '') - .''; - } - $FONTS[] = ''; - $XF = ['']; + $XF = $FONTS = $F_KEYS = $FILLS = $FL_KEYS = []; +// print_r( $this->XF ); foreach( $this->XF as $xf ) { - $align = ($xf[2] === self::A_LEFT ? ' applyAlignment="1">' : '') - .($xf[2] === self::A_RIGHT ? ' applyAlignment="1">' : '') - .($xf[2] === self::A_CENTER ? ' applyAlignment="1">' : ''); - $XF[] = 'defaultFont.'"/>' + . ( $this->defaultFontSize ? '' : '' ) + .( $xf[2] & self::F_BOLD ? '' : '') + .( $xf[2] & self::F_ITALIC ? '' : '') + .( $xf[2] & self::F_UNDERLINE ? '' : '') + .( $xf[2] & self::F_STRIKE ? '' : '') + .( $xf[2] & self::F_HYPERLINK ? '' : '') + .( $xf[2] & self::F_COLOR ? '' : '') + .''; + } + // fills + $FL_KEY = $xf[3].'-'.$xf[5]; + if (isset($FL_KEYS[$FL_KEY])) { + $FL_ID = $FL_KEYS[ $FL_KEY ]; + } else { + $FL_ID = $FL_KEYS[ $FL_KEY ] = count($FILLS); + $FILLS[] = '' : ' />') + .''; + } + $align = ($xf[1] === self::A_LEFT ? ' applyAlignment="1">' : '') + .($xf[1] === self::A_RIGHT ? ' applyAlignment="1">' : '') + .($xf[1] === self::A_CENTER ? ' applyAlignment="1">' : ''); + + $XF[] = ' 0 ? ' applyNumberFormat="1"' : '') + .($F_ID > 0 ? ' applyFont="1"' : '') + .($FL_ID > 0 ? ' applyFill="1"' : '') .($align ? $align . '' : '/>'); } + // wrap collections + array_unshift( $XF, ''); $XF[] = ''; - $FILLS = ['']; - foreach( $this->B as $fill){ - if($fill===0){ - $FILLS[] = ''; - } else { - $FILLS[] = ''; - } - } + array_unshift($FONTS, ''); + $FONTS[] = ''; + array_unshift($FILLS, ''); $FILLS[] = ''; + $template = str_replace(['{FONTS}','{XF}','{FILLS}'], [implode("\r\n", $FONTS), implode("\r\n", $XF), implode("\r\n", $FILLS)], $template); $this->_writeEntry($fh, $cdrec, $cfilename, $template); $entries++; @@ -463,7 +496,7 @@ class SimpleXLSXGen { } $ct = $cv = null; - $N = $F = $A = $C = $B = 0; + $N = $A = $F = $FL = $C = $B = 0; if ( is_string($v) ) { @@ -484,14 +517,16 @@ class SimpleXLSXGen { if ( strpos( $v, '' ) !== false ) { $F += self::F_STRIKE; } - if ( strpos( $v, ']+)>/', $v, $m ) ) { + + if ( preg_match('/ color="([^"]+)"/', $m[1], $m2) ) { + + $F += self::F_COLOR; + $C = strlen($m2[1]) === 8 ? $m2[1] : ('FF' . ltrim($m2[1],'#')); } - preg_match('/(?<= bgcolor=").*?(?=")/', $v, $bValue); - if(!empty($bValue)){ - $B = $bValue[0]; + if ( preg_match('/ bgcolor="([^"]+)"/', $m[1], $m2) ) { + $FL += self::FL_COLOR; + $B = strlen($m2[1]) === 8 ? $m2[1] : ('FF' . ltrim($m2[1],'#')); } } if ( strpos( $v, '' ) !== false ) { @@ -506,11 +541,11 @@ class SimpleXLSXGen { if ( preg_match( '/(.*?)<\/a>/i', $v, $m ) ) { $h = explode( '#', $m[1] ); $this->sheets[ $idx ]['hyperlinks'][] = ['ID' => 'rId' . ( count( $this->sheets[ $idx ]['hyperlinks'] ) + 1 ), 'R' => $cname, 'H' => $h[0], 'L' => isset( $h[1] ) ? $h[1] : '']; - $F = self::F_HYPERLINK; // Hyperlink + $F += self::F_HYPERLINK; // Hyperlink } if ( preg_match( '/(.*?)<\/a>/i', $v, $m ) ) { $this->sheets[ $idx ]['hyperlinks'][] = ['ID' => 'rId' . ( count( $this->sheets[ $idx ]['hyperlinks'] ) + 1 ), 'R' => $cname, 'H' => $m[1], 'L' => '']; - $F = self::F_HYPERLINK; // mailto hyperlink + $F += self::F_HYPERLINK; // mailto hyperlink } $v = strip_tags( $v ); } // tags @@ -547,14 +582,14 @@ class SimpleXLSXGen { $cv = $this->date2excel( $m[3], $m[2], $m[1], $m[4], $m[5], $m[6] ); $N = self::N_DATETIME; // [22] m/d/yy h:mm } elseif ( preg_match( '/^[0-9+-.]+$/', $v ) ) { // Long ? - $A = self::A_RIGHT; + $A += self::A_RIGHT; } elseif ( preg_match( '/^https?:\/\/\S+$/i', $v ) ) { $h = explode( '#', $v ); $this->sheets[ $idx ]['hyperlinks'][] = ['ID' => 'rId' . ( count( $this->sheets[ $idx ]['hyperlinks'] ) + 1 ), 'R' => $cname, 'H' => $h[0], 'L' => isset( $h[1] ) ? $h[1] : '']; - $F = self::F_HYPERLINK; // Hyperlink + $F += self::F_HYPERLINK; // Hyperlink } elseif ( preg_match( "/^[a-zA-Z0-9_\.\-]+@([a-zA-Z0-9][a-zA-Z0-9\-]*\.)+[a-zA-Z]{2,}$/", $v ) ) { $this->sheets[ $idx ]['hyperlinks'][] = ['ID' => 'rId' . ( count( $this->sheets[ $idx ]['hyperlinks'] ) + 1 ), 'R' => $cname, 'H' => 'mailto:' . $v, 'L' => '']; - $F = self::F_HYPERLINK; // Hyperlink + $F += self::F_HYPERLINK; // Hyperlink } if ( ($N === self::N_DATE || $N === self::N_DATETIME) && $cv < 0 ) { $cv = null; @@ -599,31 +634,26 @@ class SimpleXLSXGen { $COL[ $CUR_COL ] = max( $vl, $COL[ $CUR_COL ] ); $cs = 0; - if ( $N + $F + $A > 0 OR $C != 0 OR $B !=0) { - if ( isset($this->F_KEYS[ $F."-".$C ] ) ) { - $cf = $this->F_KEYS[ $F."-".$C ]; - } else { - $cf = count($this->F); - $this->F_KEYS[$F."-".$C] = $cf; - $this->F[] = $F; - $this->C[] = $C; + if ( $N + $A + $F + $FL > 0 ) { + + if ( $FL === self::FL_COLOR ) { + $FL += self::FL_SOLID; } - if ( isset($this->B_KEYS[ $B ] ) ) { - $bk = $this->B_KEYS[ $B ]; - } else { - $bk = count($this->B); - $this->B_KEYS[$B] = $bk; - $this->B[] = $B; + if ( ($F & self::F_HYPERLINK) && !($F & self::F_COLOR)) { + $F += self::F_COLOR; + $C = 'FF0563C1'; } - $NFA = 'N' . $N . 'F' . $cf . 'A' . $A . 'C'. $C . 'B' . $bk; - if ( isset( $this->XF_KEYS[ $NFA ] ) ) { - $cs = $this->XF_KEYS[ $NFA ]; + + $XF_KEY = $N . '-' . $A . '-' . $F. '-'. $FL . '-' . $C . '-' . $B; +// echo $cname .'='.$XF_KEY.PHP_EOL; + if ( isset( $this->XF_KEYS[ $XF_KEY ] ) ) { + $cs = $this->XF_KEYS[ $XF_KEY ]; } if ( $cs === 0 ) { $cs = count( $this->XF ); - $this->XF_KEYS[ $NFA ] = $cs; - $this->XF[] = [$N, $cf, $A, $C, $bk]; + $this->XF_KEYS[ $XF_KEY ] = $cs; + $this->XF[] = [$N, $A, $F, $FL, $C, $B]; } }