diff --git a/Classes/PHPExcel/Reader/Excel2007.php b/Classes/PHPExcel/Reader/Excel2007.php index 6e286937..930ff42b 100644 --- a/Classes/PHPExcel/Reader/Excel2007.php +++ b/Classes/PHPExcel/Reader/Excel2007.php @@ -68,6 +68,8 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader private $_referenceHelper = null; + private static $_theme = null; + /** * Read data only? * @@ -342,6 +344,44 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $zip = new ZipArchive; $zip->open($pFilename); + // Read the theme first, because we need the colour scheme when reading the styles + $wbRels = simplexml_load_string($this->_getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($wbRels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme": + $themeOrderArray = array('lt1','dk1','lt2','dk2'); + $themeOrderAdditional = count($themeOrderArray); + + $xmlTheme = simplexml_load_string($this->_getFromZipArchive($zip, "xl/{$rel['Target']}")); + if (is_object($xmlTheme)) { + $xmlThemeName = $xmlTheme->attributes(); + $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); + $themeName = (string)$xmlThemeName['name']; + + $colourScheme = $xmlTheme->themeElements->clrScheme->attributes(); + $colourSchemeName = (string)$colourScheme['name']; + $colourScheme = $xmlTheme->themeElements->clrScheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); + + $themeColours = array(); + foreach ($colourScheme as $k => $xmlColour) { + $themePos = array_search($k,$themeOrderArray); + if ($themePos === false) { + $themePos = $themeOrderAdditional++; + } + if (isset($xmlColour->sysClr)) { + $xmlColourData = $xmlColour->sysClr->attributes(); + $themeColours[$themePos] = $xmlColourData['lastClr']; + } elseif (isset($xmlColour->srgbClr)) { + $xmlColourData = $xmlColour->srgbClr->attributes(); + $themeColours[$themePos] = $xmlColourData['val']; + } + } + self::$_theme = new PHPExcel_Reader_Excel2007_Theme($themeName,$colourSchemeName,$themeColours); + } + break; + } + } + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($rels->Relationship as $rel) { switch ($rel["Type"]) { @@ -1464,12 +1504,26 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader return $excel; } - private static function _readColor($color) { + private static function _readColor($color, $background=false) { if (isset($color["rgb"])) { return (string)$color["rgb"]; } else if (isset($color["indexed"])) { - return PHPExcel_Style_Color::indexedColor($color["indexed"])->getARGB(); + return PHPExcel_Style_Color::indexedColor($color["indexed"],$background)->getARGB(); + } else if (isset($color["theme"])) { + if (!is_null(self::$_theme)) { + $returnColour = self::$_theme->getColourByIndex((int)$color["theme"]); + if (isset($color["tint"])) { + $tintAdjust = (float) $color["tint"]; + $returnColour = PHPExcel_Style_Color::changeBrightness($returnColour, $tintAdjust); + } + return 'FF'.$returnColour; + } } + + if ($background) { + return 'FFFFFFFF'; + } + return 'FF000000'; } private static function _readStyle($docStyle, $style) { @@ -1519,18 +1573,18 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } $docStyle->getFill()->setRotation(floatval($gradientFill["degree"])); $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - $docStyle->getFill()->getStartColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=0]"))->color) ); - $docStyle->getFill()->getEndColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=1]"))->color) ); + $docStyle->getFill()->getStartColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=0]"),true)->color) ); + $docStyle->getFill()->getEndColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=1]"),true)->color) ); } elseif ($style->fill->patternFill) { $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid'; $docStyle->getFill()->setFillType($patternType); if ($style->fill->patternFill->fgColor) { - $docStyle->getFill()->getStartColor()->setARGB(self::_readColor($style->fill->patternFill->fgColor)); + $docStyle->getFill()->getStartColor()->setARGB(self::_readColor($style->fill->patternFill->fgColor,true)); } else { $docStyle->getFill()->getStartColor()->setARGB('FF000000'); } if ($style->fill->patternFill->bgColor) { - $docStyle->getFill()->getEndColor()->setARGB(self::_readColor($style->fill->patternFill->bgColor)); + $docStyle->getFill()->getEndColor()->setARGB(self::_readColor($style->fill->patternFill->bgColor,true)); } } } diff --git a/Classes/PHPExcel/Reader/Excel2007/Theme.php b/Classes/PHPExcel/Reader/Excel2007/Theme.php new file mode 100644 index 00000000..f56e6ff9 --- /dev/null +++ b/Classes/PHPExcel/Reader/Excel2007/Theme.php @@ -0,0 +1,124 @@ +_themeName = $themeName; + $this->_colourSchemeName = $colourSchemeName; + $this->_colourMap = $colourMap; + } + + /** + * Get Theme Name + * + * @return string + */ + public function getThemeName() + { + return $this->_themeName; + } + + /** + * Get colour Scheme Name + * + * @return string + */ + public function getColourSchemeName() { + return $this->_colourSchemeName; + } + + /** + * Get colour Map Value by Position + * + * @return string + */ + public function getColourByIndex($index=0) { + if (isset($this->_colourMap[$index])) { + return $this->_colourMap[$index]; + } + return null; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if ((is_object($value)) && ($key != '_parent')) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/Classes/PHPExcel/Style/Color.php b/Classes/PHPExcel/Style/Color.php index 117c691d..e7232517 100644 --- a/Classes/PHPExcel/Style/Color.php +++ b/Classes/PHPExcel/Style/Color.php @@ -291,13 +291,78 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable return $this; } - /** + private static function _getColourComponent($RGB,$offset,$hex=true) { + $colour = substr($RGB,$offset,2); + if (!$hex) + $colour = hexdec($colour); + return $colour; + } + + public static function getRed($RGB,$hex=true) { + if (strlen($RGB) == 8) { + return self::_getColourComponent($RGB,2,$hex); + } elseif (strlen($RGB) == 6) { + return self::_getColourComponent($RGB,0,$hex); + } + } + + public static function getGreen($RGB,$hex=true) { + if (strlen($RGB) == 8) { + return self::_getColourComponent($RGB,4,$hex); + } elseif (strlen($RGB) == 6) { + return self::_getColourComponent($RGB,2,$hex); + } + } + + public static function getBlue($RGB,$hex=true) { + if (strlen($RGB) == 8) { + return self::_getColourComponent($RGB,6,$hex); + } elseif (strlen($RGB) == 6) { + return self::_getColourComponent($RGB,4,$hex); + } + } + + /** + * Adjust the brightness of a color + * + * @param string $hex The colour as an RGB value (e.g. FF00CCCC or CCDDEE + * @param float $adjustPercentage The percentage by which to adjust the colour as a float from -1 to 1 + * @return string The adjusted colour as an RGB value (e.g. FF00CCCC or CCDDEE + */ + public static function changeBrightness($hex, $adjustPercentage) { + $red = self::getRed($hex,false); + $green = self::getGreen($hex,false); + $blue = self::getBlue($hex,false); + if ($adjustPercentage > 0) { + $red += (255 - $red) * $adjustPercentage; + $green += (255 - $green) * $adjustPercentage; + $blue += (255 - $blue) * $adjustPercentage; + } else { + $red += $red * $adjustPercentage; + $green += $green * $adjustPercentage; + $blue += $blue * $adjustPercentage; + } + + if ($red < 0) $red = 0; + elseif ($red > 255) $red = 255; + if ($green < 0) $green = 0; + elseif ($green > 255) $green = 255; + if ($blue < 0) $blue = 0; + elseif ($blue > 255) $blue = 255; + + return strtoupper( str_pad(dechex($red), 2, '0', 0) . + str_pad(dechex($green), 2, '0', 0) . + str_pad(dechex($blue), 2, '0', 0) + ); + } + + /** * Get indexed color * * @param int $pIndex * @return PHPExcel_Style_Color */ - public static function indexedColor($pIndex) { + public static function indexedColor($pIndex, $background=false) { // Clean parameter $pIndex = intval($pIndex); @@ -374,7 +439,10 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable return new PHPExcel_Style_Color(self::$_indexedColors[$pIndex]); } - return new PHPExcel_Style_Color(); + if ($background) { + return new PHPExcel_Style_Color('FFFFFFFF'); + } + return new PHPExcel_Style_Color('FF000000'); } /** diff --git a/changelog.txt b/changelog.txt index c94b29a3..c293a044 100644 --- a/changelog.txt +++ b/changelog.txt @@ -35,6 +35,12 @@ Fixed in SVN: - Bugfix: (MBaker) Treat CodePage of 0 as CP1251 (for .xls files written by applications that don't set the CodePage correctly, such as Apple Numbers) - Bugfix: (MB) Work item 11583 - Need method for removing autoFilter - Bugfix: (MBaker) Work item 15029 - coordinateFromString throws exception for rows greater than 99,999 +- Bugfix: (MBaker) Work item 14999 - PHPExcel Excel2007 Reader colour problems with solidfill +- Bugfix: (MBaker) Work item 13215 - Formatting get lost and edit a template XLSX file +- Bugfix: (MBaker) Work item 14029 - Excel 2007 Reader /writer lost fontcolor +- Bugfix: (MBaker) Work item 13374 - file that makes cells go black + + 2010-12-10 (v1.7.5):