[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpexcel/PHPExcel/Reader/ -> Excel2007.php (source)

   1  <?php
   2  
   3  /** PHPExcel root directory */
   4  if (!defined('PHPEXCEL_ROOT')) {
   5      /**
   6       * @ignore
   7       */
   8      define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
   9      require (PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  10  }
  11  
  12  /**
  13   * PHPExcel_Reader_Excel2007
  14   *
  15   * Copyright (c) 2006 - 2015 PHPExcel
  16   *
  17   * This library is free software; you can redistribute it and/or
  18   * modify it under the terms of the GNU Lesser General Public
  19   * License as published by the Free Software Foundation; either
  20   * version 2.1 of the License, or (at your option) any later version.
  21   *
  22   * This library is distributed in the hope that it will be useful,
  23   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  25   * Lesser General Public License for more details.
  26   *
  27   * You should have received a copy of the GNU Lesser General Public
  28   * License along with this library; if not, write to the Free Software
  29   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  30   *
  31   * @category   PHPExcel
  32   * @package    PHPExcel_Reader
  33   * @copyright  Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  34   * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
  35   * @version    ##VERSION##, ##DATE##
  36   */
  37  class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader
  38  {
  39      /**
  40       * PHPExcel_ReferenceHelper instance
  41       *
  42       * @var PHPExcel_ReferenceHelper
  43       */
  44      private $referenceHelper = null;
  45  
  46      /**
  47       * PHPExcel_Reader_Excel2007_Theme instance
  48       *
  49       * @var PHPExcel_Reader_Excel2007_Theme
  50       */
  51      private static $theme = null;
  52  
  53      /**
  54       * Create a new PHPExcel_Reader_Excel2007 instance
  55       */
  56      public function __construct()
  57      {
  58          $this->readFilter = new PHPExcel_Reader_DefaultReadFilter();
  59          $this->referenceHelper = PHPExcel_ReferenceHelper::getInstance();
  60      }
  61  
  62      /**
  63       * Can the current PHPExcel_Reader_IReader read the file?
  64       *
  65       * @param     string         $pFilename
  66       * @return     boolean
  67       * @throws PHPExcel_Reader_Exception
  68       */
  69      public function canRead($pFilename)
  70      {
  71          // Check if file exists
  72          if (!file_exists($pFilename)) {
  73              throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
  74          }
  75  
  76          $zipClass = PHPExcel_Settings::getZipClass();
  77  
  78          // Check if zip class exists
  79  //        if (!class_exists($zipClass, false)) {
  80  //            throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled");
  81  //        }
  82  
  83          $xl = false;
  84          // Load file
  85          $zip = new $zipClass;
  86          if ($zip->open($pFilename) === true) {
  87              // check if it is an OOXML archive
  88              $rels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
  89              if ($rels !== false) {
  90                  foreach ($rels->Relationship as $rel) {
  91                      switch ($rel["Type"]) {
  92                          case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
  93                              if (basename($rel["Target"]) == 'workbook.xml') {
  94                                  $xl = true;
  95                              }
  96                              break;
  97  
  98                      }
  99                  }
 100              }
 101              $zip->close();
 102          }
 103  
 104          return $xl;
 105      }
 106  
 107  
 108      /**
 109       * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
 110       *
 111       * @param     string         $pFilename
 112       * @throws     PHPExcel_Reader_Exception
 113       */
 114      public function listWorksheetNames($pFilename)
 115      {
 116          // Check if file exists
 117          if (!file_exists($pFilename)) {
 118              throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
 119          }
 120  
 121          $worksheetNames = array();
 122  
 123          $zipClass = PHPExcel_Settings::getZipClass();
 124  
 125          $zip = new $zipClass;
 126          $zip->open($pFilename);
 127  
 128          //    The files we're looking at here are small enough that simpleXML is more efficient than XMLReader
 129          $rels = simplexml_load_string(
 130              $this->securityScan($this->getFromZipArchive($zip, "_rels/.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions())
 131          ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
 132          foreach ($rels->Relationship as $rel) {
 133              switch ($rel["Type"]) {
 134                  case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
 135                      $xmlWorkbook = simplexml_load_string(
 136                          $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions())
 137                      );  //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
 138  
 139                      if ($xmlWorkbook->sheets) {
 140                          foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
 141                              // Check if sheet should be skipped
 142                              $worksheetNames[] = (string) $eleSheet["name"];
 143                          }
 144                      }
 145              }
 146          }
 147  
 148          $zip->close();
 149  
 150          return $worksheetNames;
 151      }
 152  
 153  
 154      /**
 155       * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
 156       *
 157       * @param   string     $pFilename
 158       * @throws   PHPExcel_Reader_Exception
 159       */
 160      public function listWorksheetInfo($pFilename)
 161      {
 162          // Check if file exists
 163          if (!file_exists($pFilename)) {
 164              throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
 165          }
 166  
 167          $worksheetInfo = array();
 168  
 169          $zipClass = PHPExcel_Settings::getZipClass();
 170  
 171          $zip = new $zipClass;
 172          $zip->open($pFilename);
 173  
 174          $rels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
 175          foreach ($rels->Relationship as $rel) {
 176              if ($rel["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") {
 177                  $dir = dirname($rel["Target"]);
 178                  $relsWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());  //~ http://schemas.openxmlformats.org/package/2006/relationships");
 179                  $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships");
 180  
 181                  $worksheets = array();
 182                  foreach ($relsWorkbook->Relationship as $ele) {
 183                      if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") {
 184                          $worksheets[(string) $ele["Id"]] = $ele["Target"];
 185                      }
 186                  }
 187  
 188                  $xmlWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());  //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
 189                  if ($xmlWorkbook->sheets) {
 190                      $dir = dirname($rel["Target"]);
 191                      foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
 192                          $tmpInfo = array(
 193                              'worksheetName' => (string) $eleSheet["name"],
 194                              'lastColumnLetter' => 'A',
 195                              'lastColumnIndex' => 0,
 196                              'totalRows' => 0,
 197                              'totalColumns' => 0,
 198                          );
 199  
 200                          $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
 201  
 202                          $xml = new XMLReader();
 203                          $res = $xml->xml($this->securityScanFile('zip://'.PHPExcel_Shared_File::realpath($pFilename).'#'."$dir/$fileWorksheet"), null, PHPExcel_Settings::getLibXmlLoaderOptions());
 204                          $xml->setParserProperty(2, true);
 205  
 206                          $currCells = 0;
 207                          while ($xml->read()) {
 208                              if ($xml->name == 'row' && $xml->nodeType == XMLReader::ELEMENT) {
 209                                  $row = $xml->getAttribute('r');
 210                                  $tmpInfo['totalRows'] = $row;
 211                                  $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
 212                                  $currCells = 0;
 213                              } elseif ($xml->name == 'c' && $xml->nodeType == XMLReader::ELEMENT) {
 214                                  $currCells++;
 215                              }
 216                          }
 217                          $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
 218                          $xml->close();
 219  
 220                          $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
 221                          $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
 222  
 223                          $worksheetInfo[] = $tmpInfo;
 224                      }
 225                  }
 226              }
 227          }
 228  
 229          $zip->close();
 230  
 231          return $worksheetInfo;
 232      }
 233  
 234      private static function castToBoolean($c)
 235      {
 236  //        echo 'Initial Cast to Boolean', PHP_EOL;
 237          $value = isset($c->v) ? (string) $c->v : null;
 238          if ($value == '0') {
 239              return false;
 240          } elseif ($value == '1') {
 241              return true;
 242          } else {
 243              return (bool)$c->v;
 244          }
 245          return $value;
 246      }
 247  
 248      private static function castToError($c)
 249      {
 250  //        echo 'Initial Cast to Error', PHP_EOL;
 251          return isset($c->v) ? (string) $c->v : null;
 252      }
 253  
 254      private static function castToString($c)
 255      {
 256  //        echo 'Initial Cast to String, PHP_EOL;
 257          return isset($c->v) ? (string) $c->v : null;
 258      }
 259  
 260      private function castToFormula($c, $r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType)
 261      {
 262  //        echo 'Formula', PHP_EOL;
 263  //        echo '$c->f is ', $c->f, PHP_EOL;
 264          $cellDataType       = 'f';
 265          $value              = "={$c->f}";
 266          $calculatedValue    = self::$castBaseType($c);
 267  
 268          // Shared formula?
 269          if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') {
 270  //            echo 'SHARED FORMULA', PHP_EOL;
 271              $instance = (string)$c->f['si'];
 272  
 273  //            echo 'Instance ID = ', $instance, PHP_EOL;
 274  //
 275  //            echo 'Shared Formula Array:', PHP_EOL;
 276  //            print_r($sharedFormulas);
 277              if (!isset($sharedFormulas[(string)$c->f['si']])) {
 278  //                echo 'SETTING NEW SHARED FORMULA', PHP_EOL;
 279  //                echo 'Master is ', $r, PHP_EOL;
 280  //                echo 'Formula is ', $value, PHP_EOL;
 281                  $sharedFormulas[$instance] = array('master' => $r, 'formula' => $value);
 282  //                echo 'New Shared Formula Array:', PHP_EOL;
 283  //                print_r($sharedFormulas);
 284              } else {
 285  //                echo 'GETTING SHARED FORMULA', PHP_EOL;
 286  //                echo 'Master is ', $sharedFormulas[$instance]['master'], PHP_EOL;
 287  //                echo 'Formula is ', $sharedFormulas[$instance]['formula'], PHP_EOL;
 288                  $master = PHPExcel_Cell::coordinateFromString($sharedFormulas[$instance]['master']);
 289                  $current = PHPExcel_Cell::coordinateFromString($r);
 290  
 291                  $difference = array(0, 0);
 292                  $difference[0] = PHPExcel_Cell::columnIndexFromString($current[0]) - PHPExcel_Cell::columnIndexFromString($master[0]);
 293                  $difference[1] = $current[1] - $master[1];
 294  
 295                  $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]);
 296  //                echo 'Adjusted Formula is ', $value, PHP_EOL;
 297              }
 298          }
 299      }
 300  
 301  
 302      private function getFromZipArchive($archive, $fileName = '')
 303      {
 304          // Root-relative paths
 305          if (strpos($fileName, '//') !== false) {
 306              $fileName = substr($fileName, strpos($fileName, '//') + 1);
 307          }
 308          $fileName = PHPExcel_Shared_File::realpath($fileName);
 309  
 310          // Apache POI fixes
 311          $contents = $archive->getFromName($fileName);
 312          if ($contents === false) {
 313              $contents = $archive->getFromName(substr($fileName, 1));
 314          }
 315  
 316          return $contents;
 317      }
 318  
 319  
 320      /**
 321       * Loads PHPExcel from file
 322       *
 323       * @param     string         $pFilename
 324       * @return  PHPExcel
 325       * @throws     PHPExcel_Reader_Exception
 326       */
 327      public function load($pFilename)
 328      {
 329          // Check if file exists
 330          if (!file_exists($pFilename)) {
 331              throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
 332          }
 333  
 334          // Initialisations
 335          $excel = new PHPExcel;
 336          $excel->removeSheetByIndex(0);
 337          if (!$this->readDataOnly) {
 338              $excel->removeCellStyleXfByIndex(0); // remove the default style
 339              $excel->removeCellXfByIndex(0); // remove the default style
 340          }
 341  
 342          $zipClass = PHPExcel_Settings::getZipClass();
 343  
 344          $zip = new $zipClass;
 345          $zip->open($pFilename);
 346  
 347          //    Read the theme first, because we need the colour scheme when reading the styles
 348          $wbRels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
 349          foreach ($wbRels->Relationship as $rel) {
 350              switch ($rel["Type"]) {
 351                  case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme":
 352                      $themeOrderArray = array('lt1', 'dk1', 'lt2', 'dk2');
 353                      $themeOrderAdditional = count($themeOrderArray);
 354  
 355                      $xmlTheme = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "xl/{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
 356                      if (is_object($xmlTheme)) {
 357                          $xmlThemeName = $xmlTheme->attributes();
 358                          $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main");
 359                          $themeName = (string)$xmlThemeName['name'];
 360  
 361                          $colourScheme = $xmlTheme->themeElements->clrScheme->attributes();
 362                          $colourSchemeName = (string)$colourScheme['name'];
 363                          $colourScheme = $xmlTheme->themeElements->clrScheme->children("http://schemas.openxmlformats.org/drawingml/2006/main");
 364  
 365                          $themeColours = array();
 366                          foreach ($colourScheme as $k => $xmlColour) {
 367                              $themePos = array_search($k, $themeOrderArray);
 368                              if ($themePos === false) {
 369                                  $themePos = $themeOrderAdditional++;
 370                              }
 371                              if (isset($xmlColour->sysClr)) {
 372                                  $xmlColourData = $xmlColour->sysClr->attributes();
 373                                  $themeColours[$themePos] = $xmlColourData['lastClr'];
 374                              } elseif (isset($xmlColour->srgbClr)) {
 375                                  $xmlColourData = $xmlColour->srgbClr->attributes();
 376                                  $themeColours[$themePos] = $xmlColourData['val'];
 377                              }
 378                          }
 379                          self::$theme = new PHPExcel_Reader_Excel2007_Theme($themeName, $colourSchemeName, $themeColours);
 380                      }
 381                      break;
 382              }
 383          }
 384  
 385          $rels = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
 386          foreach ($rels->Relationship as $rel) {
 387              switch ($rel["Type"]) {
 388                  case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties":
 389                      $xmlCore = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
 390                      if (is_object($xmlCore)) {
 391                          $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/");
 392                          $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/");
 393                          $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
 394                          $docProps = $excel->getProperties();
 395                          $docProps->setCreator((string) self::getArrayItem($xmlCore->xpath("dc:creator")));
 396                          $docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath("cp:lastModifiedBy")));
 397                          $docProps->setCreated(strtotime(self::getArrayItem($xmlCore->xpath("dcterms:created")))); //! respect xsi:type
 398                          $docProps->setModified(strtotime(self::getArrayItem($xmlCore->xpath("dcterms:modified")))); //! respect xsi:type
 399                          $docProps->setTitle((string) self::getArrayItem($xmlCore->xpath("dc:title")));
 400                          $docProps->setDescription((string) self::getArrayItem($xmlCore->xpath("dc:description")));
 401                          $docProps->setSubject((string) self::getArrayItem($xmlCore->xpath("dc:subject")));
 402                          $docProps->setKeywords((string) self::getArrayItem($xmlCore->xpath("cp:keywords")));
 403                          $docProps->setCategory((string) self::getArrayItem($xmlCore->xpath("cp:category")));
 404                      }
 405                      break;
 406                  case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties":
 407                      $xmlCore = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
 408                      if (is_object($xmlCore)) {
 409                          $docProps = $excel->getProperties();
 410                          if (isset($xmlCore->Company)) {
 411                              $docProps->setCompany((string) $xmlCore->Company);
 412                          }
 413                          if (isset($xmlCore->Manager)) {
 414                              $docProps->setManager((string) $xmlCore->Manager);
 415                          }
 416                      }
 417                      break;
 418                  case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties":
 419                      $xmlCore = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
 420                      if (is_object($xmlCore)) {
 421                          $docProps = $excel->getProperties();
 422                          foreach ($xmlCore as $xmlProperty) {
 423                              $cellDataOfficeAttributes = $xmlProperty->attributes();
 424                              if (isset($cellDataOfficeAttributes['name'])) {
 425                                  $propertyName = (string) $cellDataOfficeAttributes['name'];
 426                                  $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes');
 427                                  $attributeType = $cellDataOfficeChildren->getName();
 428                                  $attributeValue = (string) $cellDataOfficeChildren->{$attributeType};
 429                                  $attributeValue = PHPExcel_DocumentProperties::convertProperty($attributeValue, $attributeType);
 430                                  $attributeType = PHPExcel_DocumentProperties::convertPropertyType($attributeType);
 431                                  $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType);
 432                              }
 433                          }
 434                      }
 435                      break;
 436                  //Ribbon
 437                  case "http://schemas.microsoft.com/office/2006/relationships/ui/extensibility":
 438                      $customUI = $rel['Target'];
 439                      if (!is_null($customUI)) {
 440                          $this->readRibbon($excel, $customUI, $zip);
 441                      }
 442                      break;
 443                  case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
 444                      $dir = dirname($rel["Target"]);
 445                      $relsWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());  //~ http://schemas.openxmlformats.org/package/2006/relationships");
 446                      $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships");
 447  
 448                      $sharedStrings = array();
 449                      $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']"));
 450                      $xmlStrings = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());  //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
 451                      if (isset($xmlStrings) && isset($xmlStrings->si)) {
 452                          foreach ($xmlStrings->si as $val) {
 453                              if (isset($val->t)) {
 454                                  $sharedStrings[] = PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $val->t);
 455                              } elseif (isset($val->r)) {
 456                                  $sharedStrings[] = $this->parseRichText($val);
 457                              }
 458                          }
 459                      }
 460  
 461                      $worksheets = array();
 462                      $macros = $customUI = null;
 463                      foreach ($relsWorkbook->Relationship as $ele) {
 464                          switch ($ele['Type']) {
 465                              case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet":
 466                                  $worksheets[(string) $ele["Id"]] = $ele["Target"];
 467                                  break;
 468                              // a vbaProject ? (: some macros)
 469                              case "http://schemas.microsoft.com/office/2006/relationships/vbaProject":
 470                                  $macros = $ele["Target"];
 471                                  break;
 472                          }
 473                      }
 474  
 475                      if (!is_null($macros)) {
 476                          $macrosCode = $this->getFromZipArchive($zip, 'xl/vbaProject.bin');//vbaProject.bin always in 'xl' dir and always named vbaProject.bin
 477                          if ($macrosCode !== false) {
 478                              $excel->setMacrosCode($macrosCode);
 479                              $excel->setHasMacros(true);
 480                              //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir
 481                              $Certificate = $this->getFromZipArchive($zip, 'xl/vbaProjectSignature.bin');
 482                              if ($Certificate !== false) {
 483                                  $excel->setMacrosCertificate($Certificate);
 484                              }
 485                          }
 486                      }
 487                      $styles     = array();
 488                      $cellStyles = array();
 489                      $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
 490                      $xmlStyles = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
 491                      //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
 492  
 493                      $numFmts = null;
 494                      if ($xmlStyles && $xmlStyles->numFmts[0]) {
 495                          $numFmts = $xmlStyles->numFmts[0];
 496                      }
 497                      if (isset($numFmts) && ($numFmts !== null)) {
 498                          $numFmts->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
 499                      }
 500                      if (!$this->readDataOnly && $xmlStyles) {
 501                          foreach ($xmlStyles->cellXfs->xf as $xf) {
 502                              $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL;
 503  
 504                              if ($xf["numFmtId"]) {
 505                                  if (isset($numFmts)) {
 506                                      $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
 507  
 508                                      if (isset($tmpNumFmt["formatCode"])) {
 509                                          $numFmt = (string) $tmpNumFmt["formatCode"];
 510                                      }
 511                                  }
 512  
 513                                  // We shouldn't override any of the built-in MS Excel values (values below id 164)
 514                                  //  But there's a lot of naughty homebrew xlsx writers that do use "reserved" id values that aren't actually used
 515                                  //  So we make allowance for them rather than lose formatting masks
 516                                  if ((int)$xf["numFmtId"] < 164 && PHPExcel_Style_NumberFormat::builtInFormatCodeIndex((int)$xf["numFmtId"]) !== false) {
 517                                      $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]);
 518                                  }
 519                              }
 520                              $quotePrefix = false;
 521                              if (isset($xf["quotePrefix"])) {
 522                                  $quotePrefix = (boolean) $xf["quotePrefix"];
 523                              }
 524  
 525                              $style = (object) array(
 526                                  "numFmt" => $numFmt,
 527                                  "font" => $xmlStyles->fonts->font[intval($xf["fontId"])],
 528                                  "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])],
 529                                  "border" => $xmlStyles->borders->border[intval($xf["borderId"])],
 530                                  "alignment" => $xf->alignment,
 531                                  "protection" => $xf->protection,
 532                                  "quotePrefix" => $quotePrefix,
 533                              );
 534                              $styles[] = $style;
 535  
 536                              // add style to cellXf collection
 537                              $objStyle = new PHPExcel_Style;
 538                              self::readStyle($objStyle, $style);
 539                              $excel->addCellXf($objStyle);
 540                          }
 541  
 542                          foreach ($xmlStyles->cellStyleXfs->xf as $xf) {
 543                              $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL;
 544                              if ($numFmts && $xf["numFmtId"]) {
 545                                  $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
 546                                  if (isset($tmpNumFmt["formatCode"])) {
 547                                      $numFmt = (string) $tmpNumFmt["formatCode"];
 548                                  } elseif ((int)$xf["numFmtId"] < 165) {
 549                                      $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]);
 550                                  }
 551                              }
 552  
 553                              $cellStyle = (object) array(
 554                                  "numFmt" => $numFmt,
 555                                  "font" => $xmlStyles->fonts->font[intval($xf["fontId"])],
 556                                  "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])],
 557                                  "border" => $xmlStyles->borders->border[intval($xf["borderId"])],
 558                                  "alignment" => $xf->alignment,
 559                                  "protection" => $xf->protection,
 560                                  "quotePrefix" => $quotePrefix,
 561                              );
 562                              $cellStyles[] = $cellStyle;
 563  
 564                              // add style to cellStyleXf collection
 565                              $objStyle = new PHPExcel_Style;
 566                              self::readStyle($objStyle, $cellStyle);
 567                              $excel->addCellStyleXf($objStyle);
 568                          }
 569                      }
 570  
 571                      $dxfs = array();
 572                      if (!$this->readDataOnly && $xmlStyles) {
 573                          //    Conditional Styles
 574                          if ($xmlStyles->dxfs) {
 575                              foreach ($xmlStyles->dxfs->dxf as $dxf) {
 576                                  $style = new PHPExcel_Style(false, true);
 577                                  self::readStyle($style, $dxf);
 578                                  $dxfs[] = $style;
 579                              }
 580                          }
 581                          //    Cell Styles
 582                          if ($xmlStyles->cellStyles) {
 583                              foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) {
 584                                  if (intval($cellStyle['builtinId']) == 0) {
 585                                      if (isset($cellStyles[intval($cellStyle['xfId'])])) {
 586                                          // Set default style
 587                                          $style = new PHPExcel_Style;
 588                                          self::readStyle($style, $cellStyles[intval($cellStyle['xfId'])]);
 589  
 590                                          // normal style, currently not using it for anything
 591                                      }
 592                                  }
 593                              }
 594                          }
 595                      }
 596  
 597                      $xmlWorkbook = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());  //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
 598  
 599                      // Set base date
 600                      if ($xmlWorkbook->workbookPr) {
 601                          PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900);
 602                          if (isset($xmlWorkbook->workbookPr['date1904'])) {
 603                              if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) {
 604                                  PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904);
 605                              }
 606                          }
 607                      }
 608  
 609                      $sheetId = 0; // keep track of new sheet id in final workbook
 610                      $oldSheetId = -1; // keep track of old sheet id in final workbook
 611                      $countSkippedSheets = 0; // keep track of number of skipped sheets
 612                      $mapSheetId = array(); // mapping of sheet ids from old to new
 613  
 614                      $charts = $chartDetails = array();
 615  
 616                      if ($xmlWorkbook->sheets) {
 617                          foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
 618                              ++$oldSheetId;
 619  
 620                              // Check if sheet should be skipped
 621                              if (isset($this->loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->loadSheetsOnly)) {
 622                                  ++$countSkippedSheets;
 623                                  $mapSheetId[$oldSheetId] = null;
 624                                  continue;
 625                              }
 626  
 627                              // Map old sheet id in original workbook to new sheet id.
 628                              // They will differ if loadSheetsOnly() is being used
 629                              $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets;
 630  
 631                              // Load sheet
 632                              $docSheet = $excel->createSheet();
 633                              //    Use false for $updateFormulaCellReferences to prevent adjustment of worksheet
 634                              //        references in formula cells... during the load, all formulae should be correct,
 635                              //        and we're simply bringing the worksheet name in line with the formula, not the
 636                              //        reverse
 637                              $docSheet->setTitle((string) $eleSheet["name"], false);
 638                              $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
 639                              $xmlSheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "$dir/$fileWorksheet")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());  //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
 640  
 641                              $sharedFormulas = array();
 642  
 643                              if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') {
 644                                  $docSheet->setSheetState((string) $eleSheet["state"]);
 645                              }
 646  
 647                              if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) {
 648                                  if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) {
 649                                      $docSheet->getSheetView()->setZoomScale(intval($xmlSheet->sheetViews->sheetView['zoomScale']));
 650                                  }
 651                                  if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) {
 652                                      $docSheet->getSheetView()->setZoomScaleNormal(intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']));
 653                                  }
 654                                  if (isset($xmlSheet->sheetViews->sheetView['view'])) {
 655                                      $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']);
 656                                  }
 657                                  if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) {
 658                                      $docSheet->setShowGridLines(self::boolean((string)$xmlSheet->sheetViews->sheetView['showGridLines']));
 659                                  }
 660                                  if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) {
 661                                      $docSheet->setShowRowColHeaders(self::boolean((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders']));
 662                                  }
 663                                  if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) {
 664                                      $docSheet->setRightToLeft(self::boolean((string)$xmlSheet->sheetViews->sheetView['rightToLeft']));
 665                                  }
 666                                  if (isset($xmlSheet->sheetViews->sheetView->pane)) {
 667                                      if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
 668                                          $docSheet->freezePane((string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell']);
 669                                      } else {
 670                                          $xSplit = 0;
 671                                          $ySplit = 0;
 672  
 673                                          if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) {
 674                                              $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']);
 675                                          }
 676  
 677                                          if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) {
 678                                              $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']);
 679                                          }
 680  
 681                                          $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit);
 682                                      }
 683                                  }
 684  
 685                                  if (isset($xmlSheet->sheetViews->sheetView->selection)) {
 686                                      if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) {
 687                                          $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref'];
 688                                          $sqref = explode(' ', $sqref);
 689                                          $sqref = $sqref[0];
 690                                          $docSheet->setSelectedCells($sqref);
 691                                      }
 692                                  }
 693                              }
 694  
 695                              if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) {
 696                                  if (isset($xmlSheet->sheetPr->tabColor['rgb'])) {
 697                                      $docSheet->getTabColor()->setARGB((string)$xmlSheet->sheetPr->tabColor['rgb']);
 698                                  }
 699                              }
 700                              if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) {
 701                                  $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']);
 702                              }
 703                              if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) {
 704                                  if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) &&
 705                                      !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) {
 706                                      $docSheet->setShowSummaryRight(false);
 707                                  } else {
 708                                      $docSheet->setShowSummaryRight(true);
 709                                  }
 710  
 711                                  if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) &&
 712                                      !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) {
 713                                      $docSheet->setShowSummaryBelow(false);
 714                                  } else {
 715                                      $docSheet->setShowSummaryBelow(true);
 716                                  }
 717                              }
 718  
 719                              if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) {
 720                                  if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) &&
 721                                      !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) {
 722                                      $docSheet->getPageSetup()->setFitToPage(false);
 723                                  } else {
 724                                      $docSheet->getPageSetup()->setFitToPage(true);
 725                                  }
 726                              }
 727  
 728                              if (isset($xmlSheet->sheetFormatPr)) {
 729                                  if (isset($xmlSheet->sheetFormatPr['customHeight']) &&
 730                                      self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) &&
 731                                      isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) {
 732                                      $docSheet->getDefaultRowDimension()->setRowHeight((float)$xmlSheet->sheetFormatPr['defaultRowHeight']);
 733                                  }
 734                                  if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) {
 735                                      $docSheet->getDefaultColumnDimension()->setWidth((float)$xmlSheet->sheetFormatPr['defaultColWidth']);
 736                                  }
 737                                  if (isset($xmlSheet->sheetFormatPr['zeroHeight']) &&
 738                                      ((string)$xmlSheet->sheetFormatPr['zeroHeight'] == '1')) {
 739                                      $docSheet->getDefaultRowDimension()->setZeroHeight(true);
 740                                  }
 741                              }
 742  
 743                              if (isset($xmlSheet->cols) && !$this->readDataOnly) {
 744                                  foreach ($xmlSheet->cols->col as $col) {
 745                                      for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) {
 746                                          if ($col["style"] && !$this->readDataOnly) {
 747                                              $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"]));
 748                                          }
 749                                          if (self::boolean($col["bestFit"])) {
 750                                              //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true);
 751                                          }
 752                                          if (self::boolean($col["hidden"])) {
 753                                          // echo PHPExcel_Cell::stringFromColumnIndex($i), ': HIDDEN COLUMN',PHP_EOL;
 754                                              $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false);
 755                                          }
 756                                          if (self::boolean($col["collapsed"])) {
 757                                              $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true);
 758                                          }
 759                                          if ($col["outlineLevel"] > 0) {
 760                                              $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"]));
 761                                          }
 762                                          $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"]));
 763  
 764                                          if (intval($col["max"]) == 16384) {
 765                                              break;
 766                                          }
 767                                      }
 768                                  }
 769                              }
 770  
 771                              if (isset($xmlSheet->printOptions) && !$this->readDataOnly) {
 772                                  if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) {
 773                                      $docSheet->setShowGridlines(true);
 774                                  }
 775                                  if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) {
 776                                      $docSheet->setPrintGridlines(true);
 777                                  }
 778                                  if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) {
 779                                      $docSheet->getPageSetup()->setHorizontalCentered(true);
 780                                  }
 781                                  if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) {
 782                                      $docSheet->getPageSetup()->setVerticalCentered(true);
 783                                  }
 784                              }
 785  
 786                              if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
 787                                  foreach ($xmlSheet->sheetData->row as $row) {
 788                                      if ($row["ht"] && !$this->readDataOnly) {
 789                                          $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"]));
 790                                      }
 791                                      if (self::boolean($row["hidden"]) && !$this->readDataOnly) {
 792                                          $docSheet->getRowDimension(intval($row["r"]))->setVisible(false);
 793                                      }
 794                                      if (self::boolean($row["collapsed"])) {
 795                                          $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true);
 796                                      }
 797                                      if ($row["outlineLevel"] > 0) {
 798                                          $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"]));
 799                                      }
 800                                      if ($row["s"] && !$this->readDataOnly) {
 801                                          $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"]));
 802                                      }
 803  
 804                                      foreach ($row->c as $c) {
 805                                          $r                     = (string) $c["r"];
 806                                          $cellDataType         = (string) $c["t"];
 807                                          $value                = null;
 808                                          $calculatedValue     = null;
 809  
 810                                          // Read cell?
 811                                          if ($this->getReadFilter() !== null) {
 812                                              $coordinates = PHPExcel_Cell::coordinateFromString($r);
 813  
 814                                              if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) {
 815                                                  continue;
 816                                              }
 817                                          }
 818  
 819      //                                    echo 'Reading cell ', $coordinates[0], $coordinates[1], PHP_EOL;
 820      //                                    print_r($c);
 821      //                                    echo PHP_EOL;
 822      //                                    echo 'Cell Data Type is ', $cellDataType, ': ';
 823      //
 824                                          // Read cell!
 825                                          switch ($cellDataType) {
 826                                              case "s":
 827      //                                            echo 'String', PHP_EOL;
 828                                                  if ((string)$c->v != '') {
 829                                                      $value = $sharedStrings[intval($c->v)];
 830  
 831                                                      if ($value instanceof PHPExcel_RichText) {
 832                                                          $value = clone $value;
 833                                                      }
 834                                                  } else {
 835                                                      $value = '';
 836                                                  }
 837                                                  break;
 838                                              case "b":
 839      //                                            echo 'Boolean', PHP_EOL;
 840                                                  if (!isset($c->f)) {
 841                                                      $value = self::castToBoolean($c);
 842                                                  } else {
 843                                                      // Formula
 844                                                      $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean');
 845                                                      if (isset($c->f['t'])) {
 846                                                          $att = array();
 847                                                          $att = $c->f;
 848                                                          $docSheet->getCell($r)->setFormulaAttributes($att);
 849                                                      }
 850      //                                                echo '$calculatedValue = ', $calculatedValue, PHP_EOL;
 851                                                  }
 852                                                  break;
 853                                              case "inlineStr":
 854  //                                                echo 'Inline String', PHP_EOL;
 855                                                  if (isset($c->f)) {
 856                                                      $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
 857                                                  } else {
 858                                                      $value = $this->parseRichText($c->is);
 859                                                  }
 860                                                  break;
 861                                              case "e":
 862      //                                            echo 'Error', PHP_EOL;
 863                                                  if (!isset($c->f)) {
 864                                                      $value = self::castToError($c);
 865                                                  } else {
 866                                                      // Formula
 867                                                      $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
 868      //                                                echo '$calculatedValue = ', $calculatedValue, PHP_EOL;
 869                                                  }
 870                                                  break;
 871                                              default:
 872  //                                                echo 'Default', PHP_EOL;
 873                                                  if (!isset($c->f)) {
 874      //                                                echo 'Not a Formula', PHP_EOL;
 875                                                      $value = self::castToString($c);
 876                                                  } else {
 877      //                                                echo 'Treat as Formula', PHP_EOL;
 878                                                      // Formula
 879                                                      $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToString');
 880      //                                                echo '$calculatedValue = ', $calculatedValue, PHP_EOL;
 881                                                  }
 882                                                  break;
 883                                          }
 884      //                                    echo 'Value is ', $value, PHP_EOL;
 885  
 886                                          // Check for numeric values
 887                                          if (is_numeric($value) && $cellDataType != 's') {
 888                                              if ($value == (int)$value) {
 889                                                  $value = (int)$value;
 890                                              } elseif ($value == (float)$value) {
 891                                                  $value = (float)$value;
 892                                              } elseif ($value == (double)$value) {
 893                                                  $value = (double)$value;
 894                                              }
 895                                          }
 896  
 897                                          // Rich text?
 898                                          if ($value instanceof PHPExcel_RichText && $this->readDataOnly) {
 899                                              $value = $value->getPlainText();
 900                                          }
 901  
 902                                          $cell = $docSheet->getCell($r);
 903                                          // Assign value
 904                                          if ($cellDataType != '') {
 905                                              $cell->setValueExplicit($value, $cellDataType);
 906                                          } else {
 907                                              $cell->setValue($value);
 908                                          }
 909                                          if ($calculatedValue !== null) {
 910                                              $cell->setCalculatedValue($calculatedValue);
 911                                          }
 912  
 913                                          // Style information?
 914                                          if ($c["s"] && !$this->readDataOnly) {
 915                                              // no style index means 0, it seems
 916                                              $cell->setXfIndex(isset($styles[intval($c["s"])]) ?
 917                                                  intval($c["s"]) : 0);
 918                                          }
 919                                      }
 920                                  }
 921                              }
 922  
 923                              $conditionals = array();
 924                              if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
 925                                  foreach ($xmlSheet->conditionalFormatting as $conditional) {
 926                                      foreach ($conditional->cfRule as $cfRule) {
 927                                          if (((string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_EXPRESSION) && isset($dxfs[intval($cfRule["dxfId"])])) {
 928                                              $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule;
 929                                          }
 930                                      }
 931                                  }
 932  
 933                                  foreach ($conditionals as $ref => $cfRules) {
 934                                      ksort($cfRules);
 935                                      $conditionalStyles = array();
 936                                      foreach ($cfRules as $cfRule) {
 937                                          $objConditional = new PHPExcel_Style_Conditional();
 938                                          $objConditional->setConditionType((string)$cfRule["type"]);
 939                                          $objConditional->setOperatorType((string)$cfRule["operator"]);
 940  
 941                                          if ((string)$cfRule["text"] != '') {
 942                                              $objConditional->setText((string)$cfRule["text"]);
 943                                          }
 944  
 945                                          if (count($cfRule->formula) > 1) {
 946                                              foreach ($cfRule->formula as $formula) {
 947                                                  $objConditional->addCondition((string)$formula);
 948                                              }
 949                                          } else {
 950                                              $objConditional->addCondition((string)$cfRule->formula);
 951                                          }
 952                                          $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]);
 953                                          $conditionalStyles[] = $objConditional;
 954                                      }
 955  
 956                                      // Extract all cell references in $ref
 957                                      foreach (PHPExcel_Cell::extractAllCellReferencesInRange($ref) as $reference) {
 958                                          $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles);
 959                                      }
 960                                  }
 961                              }
 962  
 963                              $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells");
 964                              if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
 965                                  foreach ($aKeys as $key) {
 966                                      $method = "set" . ucfirst($key);
 967                                      $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key]));
 968                                  }
 969                              }
 970  
 971                              if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
 972                                  $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true);
 973                                  if ($xmlSheet->protectedRanges->protectedRange) {
 974                                      foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
 975                                          $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true);
 976                                      }
 977                                  }
 978                              }
 979  
 980                              if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
 981                                  $autoFilterRange = (string) $xmlSheet->autoFilter["ref"];
 982                                  if (strpos($autoFilterRange, ':') !== false) {
 983                                      $autoFilter = $docSheet->getAutoFilter();
 984                                      $autoFilter->setRange($autoFilterRange);
 985  
 986                                      foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) {
 987                                          $column = $autoFilter->getColumnByOffset((integer) $filterColumn["colId"]);
 988                                          //    Check for standard filters
 989                                          if ($filterColumn->filters) {
 990                                              $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER);
 991                                              $filters = $filterColumn->filters;
 992                                              if ((isset($filters["blank"])) && ($filters["blank"] == 1)) {
 993                                                  //    Operator is undefined, but always treated as EQUAL
 994                                                  $column->createRule()->setRule(null, '')->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER);
 995                                              }
 996                                              //    Standard filters are always an OR join, so no join rule needs to be set
 997                                              //    Entries can be either filter elements
 998                                              foreach ($filters->filter as $filterRule) {
 999                                                  //    Operator is undefined, but always treated as EQUAL
1000                                                  $column->createRule()->setRule(null, (string) $filterRule["val"])->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER);
1001                                              }
1002                                              //    Or Date Group elements
1003                                              foreach ($filters->dateGroupItem as $dateGroupItem) {
1004                                                  $column->createRule()->setRule(
1005                                                      //    Operator is undefined, but always treated as EQUAL
1006                                                      null,
1007                                                      array(
1008                                                          'year' => (string) $dateGroupItem["year"],
1009                                                          'month' => (string) $dateGroupItem["month"],
1010                                                          'day' => (string) $dateGroupItem["day"],
1011                                                          'hour' => (string) $dateGroupItem["hour"],
1012                                                          'minute' => (string) $dateGroupItem["minute"],
1013                                                          'second' => (string) $dateGroupItem["second"],
1014                                                      ),
1015                                                      (string) $dateGroupItem["dateTimeGrouping"]
1016                                                  )
1017                                                  ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP);
1018                                              }
1019                                          }
1020                                          //    Check for custom filters
1021                                          if ($filterColumn->customFilters) {
1022                                              $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
1023                                              $customFilters = $filterColumn->customFilters;
1024                                              //    Custom filters can an AND or an OR join;
1025                                              //        and there should only ever be one or two entries
1026                                              if ((isset($customFilters["and"])) && ($customFilters["and"] == 1)) {
1027                                                  $column->setJoin(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND);
1028                                              }
1029                                              foreach ($customFilters->customFilter as $filterRule) {
1030                                                  $column->createRule()->setRule(
1031                                                      (string) $filterRule["operator"],
1032                                                      (string) $filterRule["val"]
1033                                                  )
1034                                                  ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
1035                                              }
1036                                          }
1037                                          //    Check for dynamic filters
1038                                          if ($filterColumn->dynamicFilter) {
1039                                              $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
1040                                              //    We should only ever have one dynamic filter
1041                                              foreach ($filterColumn->dynamicFilter as $filterRule) {
1042                                                  $column->createRule()->setRule(
1043                                                      //    Operator is undefined, but always treated as EQUAL
1044                                                      null,
1045                                                      (string) $filterRule["val"],
1046                                                      (string) $filterRule["type"]
1047                                                  )
1048                                                  ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
1049                                                  if (isset($filterRule["val"])) {
1050                                                      $column->setAttribute('val', (string) $filterRule["val"]);
1051                                                  }
1052                                                  if (isset($filterRule["maxVal"])) {
1053                                                      $column->setAttribute('maxVal', (string) $filterRule["maxVal"]);
1054                                                  }
1055                                              }
1056                                          }
1057                                          //    Check for dynamic filters
1058                                          if ($filterColumn->top10) {
1059                                              $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER);
1060                                              //    We should only ever have one top10 filter
1061                                              foreach ($filterColumn->top10 as $filterRule) {
1062                                                  $column->createRule()->setRule(
1063                                                      (((isset($filterRule["percent"])) && ($filterRule["percent"] == 1))
1064                                                          ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT
1065                                                          : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE
1066                                                      ),
1067                                                      (string) $filterRule["val"],
1068                                                      (((isset($filterRule["top"])) && ($filterRule["top"] == 1))
1069                                                          ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP
1070                                                          : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM
1071                                                      )
1072                                                  )
1073                                                  ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_TOPTENFILTER);
1074                                              }
1075                                          }
1076                                      }
1077                                  }
1078                              }
1079  
1080                              if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
1081                                  foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) {
1082                                      $mergeRef = (string) $mergeCell["ref"];
1083                                      if (strpos($mergeRef, ':') !== false) {
1084                                          $docSheet->mergeCells((string) $mergeCell["ref"]);
1085                                      }
1086                                  }
1087                              }
1088  
1089                              if ($xmlSheet && $xmlSheet->pageMargins && !$this->readDataOnly) {
1090                                  $docPageMargins = $docSheet->getPageMargins();
1091                                  $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"]));
1092                                  $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"]));
1093                                  $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"]));
1094                                  $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"]));
1095                                  $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"]));
1096                                  $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"]));
1097                              }
1098  
1099                              if ($xmlSheet && $xmlSheet->pageSetup && !$this->readDataOnly) {
1100                                  $docPageSetup = $docSheet->getPageSetup();
1101  
1102                                  if (isset($xmlSheet->pageSetup["orientation"])) {
1103                                      $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]);
1104                                  }
1105                                  if (isset($xmlSheet->pageSetup["paperSize"])) {
1106                                      $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"]));
1107                                  }
1108                                  if (isset($xmlSheet->pageSetup["scale"])) {
1109                                      $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), false);
1110                                  }
1111                                  if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) {
1112                                      $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), false);
1113                                  }
1114                                  if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) {
1115                                      $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), false);
1116                                  }
1117                                  if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) &&
1118                                      self::boolean((string) $xmlSheet->pageSetup["useFirstPageNumber"])) {
1119                                      $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"]));
1120                                  }
1121                              }
1122  
1123                              if ($xmlSheet && $xmlSheet->headerFooter && !$this->readDataOnly) {
1124                                  $docHeaderFooter = $docSheet->getHeaderFooter();
1125  
1126                                  if (isset($xmlSheet->headerFooter["differentOddEven"]) &&
1127                                      self::boolean((string)$xmlSheet->headerFooter["differentOddEven"])) {
1128                                      $docHeaderFooter->setDifferentOddEven(true);
1129                                  } else {
1130                                      $docHeaderFooter->setDifferentOddEven(false);
1131                                  }
1132                                  if (isset($xmlSheet->headerFooter["differentFirst"]) &&
1133                                      self::boolean((string)$xmlSheet->headerFooter["differentFirst"])) {
1134                                      $docHeaderFooter->setDifferentFirst(true);
1135                                  } else {
1136                                      $docHeaderFooter->setDifferentFirst(false);
1137                                  }
1138                                  if (isset($xmlSheet->headerFooter["scaleWithDoc"]) &&
1139                                      !self::boolean((string)$xmlSheet->headerFooter["scaleWithDoc"])) {
1140                                      $docHeaderFooter->setScaleWithDocument(false);
1141                                  } else {
1142                                      $docHeaderFooter->setScaleWithDocument(true);
1143                                  }
1144                                  if (isset($xmlSheet->headerFooter["alignWithMargins"]) &&
1145                                      !self::boolean((string)$xmlSheet->headerFooter["alignWithMargins"])) {
1146                                      $docHeaderFooter->setAlignWithMargins(false);
1147                                  } else {
1148                                      $docHeaderFooter->setAlignWithMargins(true);
1149                                  }
1150  
1151                                  $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader);
1152                                  $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter);
1153                                  $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader);
1154                                  $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter);
1155                                  $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader);
1156                                  $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter);
1157                              }
1158  
1159                              if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->readDataOnly) {
1160                                  foreach ($xmlSheet->rowBreaks->brk as $brk) {
1161                                      if ($brk["man"]) {
1162                                          $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW);
1163                                      }
1164                                  }
1165                              }
1166                              if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->readDataOnly) {
1167                                  foreach ($xmlSheet->colBreaks->brk as $brk) {
1168                                      if ($brk["man"]) {
1169                                          $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex((string) $brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN);
1170                                      }
1171                                  }
1172                              }
1173  
1174                              if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) {
1175                                  foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) {
1176                                      // Uppercase coordinate
1177                                      $range = strtoupper($dataValidation["sqref"]);
1178                                      $rangeSet = explode(' ', $range);
1179                                      foreach ($rangeSet as $range) {
1180                                          $stRange = $docSheet->shrinkRangeToFit($range);
1181  
1182                                          // Extract all cell references in $range
1183                                          foreach (PHPExcel_Cell::extractAllCellReferencesInRange($stRange) as $reference) {
1184                                              // Create validation
1185                                              $docValidation = $docSheet->getCell($reference)->getDataValidation();
1186                                              $docValidation->setType((string) $dataValidation["type"]);
1187                                              $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]);
1188                                              $docValidation->setOperator((string) $dataValidation["operator"]);
1189                                              $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0);
1190                                              $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0);
1191                                              $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0);
1192                                              $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0);
1193                                              $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]);
1194                                              $docValidation->setError((string) $dataValidation["error"]);
1195                                              $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]);
1196                                              $docValidation->setPrompt((string) $dataValidation["prompt"]);
1197                                              $docValidation->setFormula1((string) $dataValidation->formula1);
1198                                              $docValidation->setFormula2((string) $dataValidation->formula2);
1199                                          }
1200                                      }
1201                                  }
1202                              }
1203  
1204                              // Add hyperlinks
1205                              $hyperlinks = array();
1206                              if (!$this->readDataOnly) {
1207                                  // Locate hyperlink relations
1208                                  if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1209                                      $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1210                                      foreach ($relsWorksheet->Relationship as $ele) {
1211                                          if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") {
1212                                              $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"];
1213                                          }
1214                                      }
1215                                  }
1216  
1217                                  // Loop through hyperlinks
1218                                  if ($xmlSheet && $xmlSheet->hyperlinks) {
1219                                      foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) {
1220                                          // Link url
1221                                          $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1222  
1223                                          foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
1224                                              $cell = $docSheet->getCell($cellReference);
1225                                              if (isset($linkRel['id'])) {
1226                                                  $hyperlinkUrl = $hyperlinks[ (string)$linkRel['id'] ];
1227                                                  if (isset($hyperlink['location'])) {
1228                                                      $hyperlinkUrl .= '#' . (string) $hyperlink['location'];
1229                                                  }
1230                                                  $cell->getHyperlink()->setUrl($hyperlinkUrl);
1231                                              } elseif (isset($hyperlink['location'])) {
1232                                                  $cell->getHyperlink()->setUrl('sheet://' . (string)$hyperlink['location']);
1233                                              }
1234  
1235                                              // Tooltip
1236                                              if (isset($hyperlink['tooltip'])) {
1237                                                  $cell->getHyperlink()->setTooltip((string)$hyperlink['tooltip']);
1238                                              }
1239                                          }
1240                                      }
1241                                  }
1242                              }
1243  
1244                              // Add comments
1245                              $comments = array();
1246                              $vmlComments = array();
1247                              if (!$this->readDataOnly) {
1248                                  // Locate comment relations
1249                                  if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1250                                      $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1251                                      foreach ($relsWorksheet->Relationship as $ele) {
1252                                          if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") {
1253                                              $comments[(string)$ele["Id"]] = (string)$ele["Target"];
1254                                          }
1255                                          if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
1256                                              $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"];
1257                                          }
1258                                      }
1259                                  }
1260  
1261                                  // Loop through comments
1262                                  foreach ($comments as $relName => $relPath) {
1263                                      // Load comments file
1264                                      $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath);
1265                                      $commentsFile = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
1266  
1267                                      // Utility variables
1268                                      $authors = array();
1269  
1270                                      // Loop through authors
1271                                      foreach ($commentsFile->authors->author as $author) {
1272                                          $authors[] = (string)$author;
1273                                      }
1274  
1275                                      // Loop through contents
1276                                      foreach ($commentsFile->commentList->comment as $comment) {
1277                                          if (!empty($comment['authorId'])) {
1278                                              $docSheet->getComment((string)$comment['ref'])->setAuthor($authors[(string)$comment['authorId']]);
1279                                          }
1280                                          $docSheet->getComment((string)$comment['ref'])->setText($this->parseRichText($comment->text));
1281                                      }
1282                                  }
1283  
1284                                  // Loop through VML comments
1285                                  foreach ($vmlComments as $relName => $relPath) {
1286                                      // Load VML comments file
1287                                      $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath);
1288                                      $vmlCommentsFile = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $relPath)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
1289                                      $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1290  
1291                                      $shapes = $vmlCommentsFile->xpath('//v:shape');
1292                                      foreach ($shapes as $shape) {
1293                                          $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1294  
1295                                          if (isset($shape['style'])) {
1296                                              $style        = (string)$shape['style'];
1297                                              $fillColor    = strtoupper(substr((string)$shape['fillcolor'], 1));
1298                                              $column       = null;
1299                                              $row          = null;
1300  
1301                                              $clientData   = $shape->xpath('.//x:ClientData');
1302                                              if (is_array($clientData) && !empty($clientData)) {
1303                                                  $clientData   = $clientData[0];
1304  
1305                                                  if (isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note') {
1306                                                      $temp = $clientData->xpath('.//x:Row');
1307                                                      if (is_array($temp)) {
1308                                                          $row = $temp[0];
1309                                                      }
1310  
1311                                                      $temp = $clientData->xpath('.//x:Column');
1312                                                      if (is_array($temp)) {
1313                                                          $column = $temp[0];
1314                                                      }
1315                                                  }
1316                                              }
1317  
1318                                              if (($column !== null) && ($row !== null)) {
1319                                                  // Set comment properties
1320                                                  $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1);
1321                                                  $comment->getFillColor()->setRGB($fillColor);
1322  
1323                                                  // Parse style
1324                                                  $styleArray = explode(';', str_replace(' ', '', $style));
1325                                                  foreach ($styleArray as $stylePair) {
1326                                                      $stylePair = explode(':', $stylePair);
1327  
1328                                                      if ($stylePair[0] == 'margin-left') {
1329                                                          $comment->setMarginLeft($stylePair[1]);
1330                                                      }
1331                                                      if ($stylePair[0] == 'margin-top') {
1332                                                          $comment->setMarginTop($stylePair[1]);
1333                                                      }
1334                                                      if ($stylePair[0] == 'width') {
1335                                                          $comment->setWidth($stylePair[1]);
1336                                                      }
1337                                                      if ($stylePair[0] == 'height') {
1338                                                          $comment->setHeight($stylePair[1]);
1339                                                      }
1340                                                      if ($stylePair[0] == 'visibility') {
1341                                                          $comment->setVisible($stylePair[1] == 'visible');
1342                                                      }
1343                                                  }
1344                                              }
1345                                          }
1346                                      }
1347                                  }
1348  
1349                                  // Header/footer images
1350                                  if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->readDataOnly) {
1351                                      if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1352                                          $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1353                                          $vmlRelationship = '';
1354  
1355                                          foreach ($relsWorksheet->Relationship as $ele) {
1356                                              if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
1357                                                  $vmlRelationship = self::dirAdd("$dir/$fileWorksheet", $ele["Target"]);
1358                                              }
1359                                          }
1360  
1361                                          if ($vmlRelationship != '') {
1362                                              // Fetch linked images
1363                                              $relsVML = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels')), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1364                                              $drawings = array();
1365                                              foreach ($relsVML->Relationship as $ele) {
1366                                                  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") {
1367                                                      $drawings[(string) $ele["Id"]] = self::dirAdd($vmlRelationship, $ele["Target"]);
1368                                                  }
1369                                              }
1370  
1371                                              // Fetch VML document
1372                                              $vmlDrawing = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $vmlRelationship)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
1373                                              $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1374  
1375                                              $hfImages = array();
1376  
1377                                              $shapes = $vmlDrawing->xpath('//v:shape');
1378                                              foreach ($shapes as $idx => $shape) {
1379                                                  $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1380                                                  $imageData = $shape->xpath('//v:imagedata');
1381                                                  $imageData = $imageData[$idx];
1382  
1383                                                  $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office');
1384                                                  $style = self::toCSSArray((string)$shape['style']);
1385  
1386                                                  $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing();
1387                                                  if (isset($imageData['title'])) {
1388                                                      $hfImages[ (string)$shape['id'] ]->setName((string)$imageData['title']);
1389                                                  }
1390  
1391                                                  $hfImages[ (string)$shape['id'] ]->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $drawings[(string)$imageData['relid']], false);
1392                                                  $hfImages[ (string)$shape['id'] ]->setResizeProportional(false);
1393                                                  $hfImages[ (string)$shape['id'] ]->setWidth($style['width']);
1394                                                  $hfImages[ (string)$shape['id'] ]->setHeight($style['height']);
1395                                                  if (isset($style['margin-left'])) {
1396                                                      $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']);
1397                                                  }
1398                                                  $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']);
1399                                                  $hfImages[ (string)$shape['id'] ]->setResizeProportional(true);
1400                                              }
1401  
1402                                              $docSheet->getHeaderFooter()->setImages($hfImages);
1403                                          }
1404                                      }
1405                                  }
1406  
1407                              }
1408  
1409                              // TODO: Autoshapes from twoCellAnchors!
1410                              if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1411                                  $relsWorksheet = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1412                                  $drawings = array();
1413                                  foreach ($relsWorksheet->Relationship as $ele) {
1414                                      if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") {
1415                                          $drawings[(string) $ele["Id"]] = self::dirAdd("$dir/$fileWorksheet", $ele["Target"]);
1416                                      }
1417                                  }
1418                                  if ($xmlSheet->drawing && !$this->readDataOnly) {
1419                                      foreach ($xmlSheet->drawing as $drawing) {
1420                                          $fileDrawing = $drawings[(string) self::getArrayItem($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
1421                                          $relsDrawing = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships");
1422                                          $images = array();
1423  
1424                                          if ($relsDrawing && $relsDrawing->Relationship) {
1425                                              foreach ($relsDrawing->Relationship as $ele) {
1426                                                  if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") {
1427                                                      $images[(string) $ele["Id"]] = self::dirAdd($fileDrawing, $ele["Target"]);
1428                                                  } elseif ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart") {
1429                                                      if ($this->includeCharts) {
1430                                                          $charts[self::dirAdd($fileDrawing, $ele["Target"])] = array(
1431                                                              'id'        => (string) $ele["Id"],
1432                                                              'sheet'    => $docSheet->getTitle()
1433                                                          );
1434                                                      }
1435                                                  }
1436                                              }
1437                                          }
1438                                          $xmlDrawing = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $fileDrawing)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions())->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing");
1439  
1440                                          if ($xmlDrawing->oneCellAnchor) {
1441                                              foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) {
1442                                                  if ($oneCellAnchor->pic->blipFill) {
1443                                                      $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip;
1444                                                      $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm;
1445                                                      $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw;
1446                                                      $objDrawing = new PHPExcel_Worksheet_Drawing;
1447                                                      $objDrawing->setName((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name"));
1448                                                      $objDrawing->setDescription((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr"));
1449                                                      $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::getArrayItem($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false);
1450                                                      $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1));
1451                                                      $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff));
1452                                                      $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff));
1453                                                      $objDrawing->setResizeProportional(false);
1454                                                      $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cx")));
1455                                                      $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cy")));
1456                                                      if ($xfrm) {
1457                                                          $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), "rot")));
1458                                                      }
1459                                                      if ($outerShdw) {
1460                                                          $shadow = $objDrawing->getShadow();
1461                                                          $shadow->setVisible(true);
1462                                                          $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "blurRad")));
1463                                                          $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "dist")));
1464                                                          $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), "dir")));
1465                                                          $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), "algn"));
1466                                                          $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), "val"));
1467                                                          $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), "val") / 1000);
1468                                                      }
1469                                                      $objDrawing->setWorksheet($docSheet);
1470                                                  } else {
1471                                                      //    ? Can charts be positioned with a oneCellAnchor ?
1472                                                      $coordinates    = PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1);
1473                                                      $offsetX        = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff);
1474                                                      $offsetY        = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff);
1475                                                      $width          = PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cx"));
1476                                                      $height         = PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cy"));
1477                                                  }
1478                                              }
1479                                          }
1480                                          if ($xmlDrawing->twoCellAnchor) {
1481                                              foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) {
1482                                                  if ($twoCellAnchor->pic->blipFill) {
1483                                                      $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip;
1484                                                      $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm;
1485                                                      $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw;
1486                                                      $objDrawing = new PHPExcel_Worksheet_Drawing;
1487                                                      $objDrawing->setName((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name"));
1488                                                      $objDrawing->setDescription((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr"));
1489                                                      $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::getArrayItem($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false);
1490                                                      $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1));
1491                                                      $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff));
1492                                                      $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff));
1493                                                      $objDrawing->setResizeProportional(false);
1494  
1495                                                      if ($xfrm) {
1496                                                          $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), "cx")));
1497                                                          $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), "cy")));
1498                                                          $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), "rot")));
1499                                                      }
1500                                                      if ($outerShdw) {
1501                                                          $shadow = $objDrawing->getShadow();
1502                                                          $shadow->setVisible(true);
1503                                                          $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "blurRad")));
1504                                                          $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "dist")));
1505                                                          $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), "dir")));
1506                                                          $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), "algn"));
1507                                                          $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), "val"));
1508                                                          $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), "val") / 1000);
1509                                                      }
1510                                                      $objDrawing->setWorksheet($docSheet);
1511                                                  } elseif (($this->includeCharts) && ($twoCellAnchor->graphicFrame)) {
1512                                                      $fromCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1);
1513                                                      $fromOffsetX    = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff);
1514                                                      $fromOffsetY    = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff);
1515                                                      $toCoordinate   = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1);
1516                                                      $toOffsetX      = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->colOff);
1517                                                      $toOffsetY      = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->rowOff);
1518                                                      $graphic        = $twoCellAnchor->graphicFrame->children("http://schemas.openxmlformats.org/drawingml/2006/main")->graphic;
1519                                                      $chartRef       = $graphic->graphicData->children("http://schemas.openxmlformats.org/drawingml/2006/chart")->chart;
1520                                                      $thisChart      = (string) $chartRef->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
1521  
1522                                                      $chartDetails[$docSheet->getTitle().'!'.$thisChart] = array(
1523                                                          'fromCoordinate'    => $fromCoordinate,
1524                                                          'fromOffsetX'       => $fromOffsetX,
1525                                                          'fromOffsetY'       => $fromOffsetY,
1526                                                          'toCoordinate'      => $toCoordinate,
1527                                                          'toOffsetX'         => $toOffsetX,
1528                                                          'toOffsetY'         => $toOffsetY,
1529                                                          'worksheetTitle'    => $docSheet->getTitle()
1530                                                      );
1531                                                  }
1532                                              }
1533                                          }
1534                                      }
1535                                  }
1536                              }
1537  
1538                              // Loop through definedNames
1539                              if ($xmlWorkbook->definedNames) {
1540                                  foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1541                                      // Extract range
1542                                      $extractedRange = (string)$definedName;
1543                                      $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange);
1544                                      if (($spos = strpos($extractedRange, '!')) !== false) {
1545                                          $extractedRange = substr($extractedRange, 0, $spos).str_replace('$', '', substr($extractedRange, $spos));
1546                                      } else {
1547                                          $extractedRange = str_replace('$', '', $extractedRange);
1548                                      }
1549  
1550                                      // Valid range?
1551                                      if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') {
1552                                          continue;
1553                                      }
1554  
1555                                      // Some definedNames are only applicable if we are on the same sheet...
1556                                      if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) {
1557                                          // Switch on type
1558                                          switch ((string)$definedName['name']) {
1559                                              case '_xlnm._FilterDatabase':
1560                                                  if ((string)$definedName['hidden'] !== '1') {
1561                                                      $extractedRange = explode(',', $extractedRange);
1562                                                      foreach ($extractedRange as $range) {
1563                                                          $autoFilterRange = $range;
1564                                                          if (strpos($autoFilterRange, ':') !== false) {
1565                                                              $docSheet->getAutoFilter()->setRange($autoFilterRange);
1566                                                          }
1567                                                      }
1568                                                  }
1569                                                  break;
1570                                              case '_xlnm.Print_Titles':
1571                                                  // Split $extractedRange
1572                                                  $extractedRange = explode(',', $extractedRange);
1573  
1574                                                  // Set print titles
1575                                                  foreach ($extractedRange as $range) {
1576                                                      $matches = array();
1577                                                      $range = str_replace('$', '', $range);
1578  
1579                                                      // check for repeating columns, e g. 'A:A' or 'A:D'
1580                                                      if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) {
1581                                                          $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2]));
1582                                                      } elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) {
1583                                                          // check for repeating rows, e.g. '1:1' or '1:5'
1584                                                          $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2]));
1585                                                      }
1586                                                  }
1587                                                  break;
1588                                              case '_xlnm.Print_Area':
1589                                                  $rangeSets = explode(',', $extractedRange);        // FIXME: what if sheetname contains comma?
1590                                                  $newRangeSets = array();
1591                                                  foreach ($rangeSets as $rangeSet) {
1592                                                      $range = explode('!', $rangeSet);    // FIXME: what if sheetname contains exclamation mark?
1593                                                      $rangeSet = isset($range[1]) ? $range[1] : $range[0];
1594                                                      if (strpos($rangeSet, ':') === false) {
1595                                                          $rangeSet = $rangeSet . ':' . $rangeSet;
1596                                                      }
1597                                                      $newRangeSets[] = str_replace('$', '', $rangeSet);
1598                                                  }
1599                                                  $docSheet->getPageSetup()->setPrintArea(implode(',', $newRangeSets));
1600                                                  break;
1601  
1602                                              default:
1603                                                  break;
1604                                          }
1605                                      }
1606                                  }
1607                              }
1608  
1609                              // Next sheet id
1610                              ++$sheetId;
1611                          }
1612  
1613                          // Loop through definedNames
1614                          if ($xmlWorkbook->definedNames) {
1615                              foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1616                                  // Extract range
1617                                  $extractedRange = (string)$definedName;
1618                                  $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange);
1619                                  if (($spos = strpos($extractedRange, '!')) !== false) {
1620                                      $extractedRange = substr($extractedRange, 0, $spos).str_replace('$', '', substr($extractedRange, $spos));
1621                                  } else {
1622                                      $extractedRange = str_replace('$', '', $extractedRange);
1623                                  }
1624  
1625                                  // Valid range?
1626                                  if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') {
1627                                      continue;
1628                                  }
1629  
1630                                  // Some definedNames are only applicable if we are on the same sheet...
1631                                  if ((string)$definedName['localSheetId'] != '') {
1632                                      // Local defined name
1633                                      // Switch on type
1634                                      switch ((string)$definedName['name']) {
1635                                          case '_xlnm._FilterDatabase':
1636                                          case '_xlnm.Print_Titles':
1637                                          case '_xlnm.Print_Area':
1638                                              break;
1639                                          default:
1640                                              if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) {
1641                                                  $range = explode('!', (string)$definedName);
1642                                                  if (count($range) == 2) {
1643                                                      $range[0] = str_replace("''", "'", $range[0]);
1644                                                      $range[0] = str_replace("'", "", $range[0]);
1645                                                      if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) {
1646                                                          $extractedRange = str_replace('$', '', $range[1]);
1647                                                          $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $definedName['localSheetId']]);
1648                                                          $excel->addNamedRange(new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope));
1649                                                      }
1650                                                  }
1651                                              }
1652                                              break;
1653                                      }
1654                                  } elseif (!isset($definedName['localSheetId'])) {
1655                                      // "Global" definedNames
1656                                      $locatedSheet = null;
1657                                      $extractedSheetName = '';
1658                                      if (strpos((string)$definedName, '!') !== false) {
1659                                          // Extract sheet name
1660                                          $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle((string)$definedName, true);
1661                                          $extractedSheetName = $extractedSheetName[0];
1662  
1663                                          // Locate sheet
1664                                          $locatedSheet = $excel->getSheetByName($extractedSheetName);
1665  
1666                                          // Modify range
1667                                          $range = explode('!', $extractedRange);
1668                                          $extractedRange = isset($range[1]) ? $range[1] : $range[0];
1669                                      }
1670  
1671                                      if ($locatedSheet !== null) {
1672                                          $excel->addNamedRange(new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false));
1673                                      }
1674                                  }
1675                              }
1676                          }
1677                      }
1678  
1679                      if ((!$this->readDataOnly) || (!empty($this->loadSheetsOnly))) {
1680                          // active sheet index
1681                          $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index
1682  
1683                          // keep active sheet index if sheet is still loaded, else first sheet is set as the active
1684                          if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
1685                              $excel->setActiveSheetIndex($mapSheetId[$activeTab]);
1686                          } else {
1687                              if ($excel->getSheetCount() == 0) {
1688                                  $excel->createSheet();
1689                              }
1690                              $excel->setActiveSheetIndex(0);
1691                          }
1692                      }
1693                      break;
1694              }
1695          }
1696  
1697          if (!$this->readDataOnly) {
1698              $contentTypes = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, "[Content_Types].xml")), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
1699              foreach ($contentTypes->Override as $contentType) {
1700                  switch ($contentType["ContentType"]) {
1701                      case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml":
1702                          if ($this->includeCharts) {
1703                              $chartEntryRef = ltrim($contentType['PartName'], '/');
1704                              $chartElements = simplexml_load_string($this->securityScan($this->getFromZipArchive($zip, $chartEntryRef)), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
1705                              $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements, basename($chartEntryRef, '.xml'));
1706  
1707  //                            echo 'Chart ', $chartEntryRef, '<br />';
1708  //                            var_dump($charts[$chartEntryRef]);
1709  //
1710                              if (isset($charts[$chartEntryRef])) {
1711                                  $chartPositionRef = $charts[$chartEntryRef]['sheet'].'!'.$charts[$chartEntryRef]['id'];
1712  //                                echo 'Position Ref ', $chartPositionRef, '<br />';
1713                                  if (isset($chartDetails[$chartPositionRef])) {
1714  //                                    var_dump($chartDetails[$chartPositionRef]);
1715  
1716                                      $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart);
1717                                      $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet']));
1718                                      $objChart->setTopLeftPosition($chartDetails[$chartPositionRef]['fromCoordinate'], $chartDetails[$chartPositionRef]['fromOffsetX'], $chartDetails[$chartPositionRef]['fromOffsetY']);
1719                                      $objChart->setBottomRightPosition($chartDetails[$chartPositionRef]['toCoordinate'], $chartDetails[$chartPositionRef]['toOffsetX'], $chartDetails[$chartPositionRef]['toOffsetY']);
1720                                  }
1721                              }
1722                          }
1723                  }
1724              }
1725          }
1726  
1727          $zip->close();
1728  
1729          return $excel;
1730      }
1731  
1732      private static function readColor($color, $background = false)
1733      {
1734          if (isset($color["rgb"])) {
1735              return (string)$color["rgb"];
1736          } elseif (isset($color["indexed"])) {
1737              return PHPExcel_Style_Color::indexedColor($color["indexed"]-7, $background)->getARGB();
1738          } elseif (isset($color["theme"])) {
1739              if (self::$theme !== null) {
1740                  $returnColour = self::$theme->getColourByIndex((int)$color["theme"]);
1741                  if (isset($color["tint"])) {
1742                      $tintAdjust = (float) $color["tint"];
1743                      $returnColour = PHPExcel_Style_Color::changeBrightness($returnColour, $tintAdjust);
1744                  }
1745                  return 'FF'.$returnColour;
1746              }
1747          }
1748  
1749          if ($background) {
1750              return 'FFFFFFFF';
1751          }
1752          return 'FF000000';
1753      }
1754  
1755      private static function readStyle($docStyle, $style)
1756      {
1757          // format code
1758  //        if (isset($style->numFmt)) {
1759  //            if (isset($style->numFmt['formatCode'])) {
1760  //                $docStyle->getNumberFormat()->setFormatCode((string) $style->numFmt['formatCode']);
1761  //            } else {
1762                  $docStyle->getNumberFormat()->setFormatCode($style->numFmt);
1763  //            }
1764  //        }
1765  
1766          // font
1767          if (isset($style->font)) {
1768              $docStyle->getFont()->setName((string) $style->font->name["val"]);
1769              $docStyle->getFont()->setSize((string) $style->font->sz["val"]);
1770              if (isset($style->font->b)) {
1771                  $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || self::boolean((string) $style->font->b["val"]));
1772              }
1773              if (isset($style->font->i)) {
1774                  $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || self::boolean((string) $style->font->i["val"]));
1775              }
1776              if (isset($style->font->strike)) {
1777                  $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || self::boolean((string) $style->font->strike["val"]));
1778              }
1779              $docStyle->getFont()->getColor()->setARGB(self::readColor($style->font->color));
1780  
1781              if (isset($style->font->u) && !isset($style->font->u["val"])) {
1782                  $docStyle->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE);
1783              } elseif (isset($style->font->u) && isset($style->font->u["val"])) {
1784                  $docStyle->getFont()->setUnderline((string)$style->font->u["val"]);
1785              }
1786  
1787              if (isset($style->font->vertAlign) && isset($style->font->vertAlign["val"])) {
1788                  $vertAlign = strtolower((string)$style->font->vertAlign["val"]);
1789                  if ($vertAlign == 'superscript') {
1790                      $docStyle->getFont()->setSuperScript(true);
1791                  }
1792                  if ($vertAlign == 'subscript') {
1793                      $docStyle->getFont()->setSubScript(true);
1794                  }
1795              }
1796          }
1797  
1798          // fill
1799          if (isset($style->fill)) {
1800              if ($style->fill->gradientFill) {
1801                  $gradientFill = $style->fill->gradientFill[0];
1802                  if (!empty($gradientFill["type"])) {
1803                      $docStyle->getFill()->setFillType((string) $gradientFill["type"]);
1804                  }
1805                  $docStyle->getFill()->setRotation(floatval($gradientFill["degree"]));
1806                  $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
1807                  $docStyle->getFill()->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath("sml:stop[@position=0]"))->color));
1808                  $docStyle->getFill()->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath("sml:stop[@position=1]"))->color));
1809              } elseif ($style->fill->patternFill) {
1810                  $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid';
1811                  $docStyle->getFill()->setFillType($patternType);
1812                  if ($style->fill->patternFill->fgColor) {
1813                      $docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true));
1814                  } else {
1815                      $docStyle->getFill()->getStartColor()->setARGB('FF000000');
1816                  }
1817                  if ($style->fill->patternFill->bgColor) {
1818                      $docStyle->getFill()->getEndColor()->setARGB(self::readColor($style->fill->patternFill->bgColor, true));
1819                  }
1820              }
1821          }
1822  
1823          // border
1824          if (isset($style->border)) {
1825              $diagonalUp = self::boolean((string) $style->border["diagonalUp"]);
1826              $diagonalDown = self::boolean((string) $style->border["diagonalDown"]);
1827              if (!$diagonalUp && !$diagonalDown) {
1828                  $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE);
1829              } elseif ($diagonalUp && !$diagonalDown) {
1830                  $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP);
1831              } elseif (!$diagonalUp && $diagonalDown) {
1832                  $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN);
1833              } else {
1834                  $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH);
1835              }
1836              self::readBorder($docStyle->getBorders()->getLeft(), $style->border->left);
1837              self::readBorder($docStyle->getBorders()->getRight(), $style->border->right);
1838              self::readBorder($docStyle->getBorders()->getTop(), $style->border->top);
1839              self::readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom);
1840              self::readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal);
1841          }
1842  
1843          // alignment
1844          if (isset($style->alignment)) {
1845              $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]);
1846              $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]);
1847  
1848              $textRotation = 0;
1849              if ((int)$style->alignment["textRotation"] <= 90) {
1850                  $textRotation = (int)$style->alignment["textRotation"];
1851              } elseif ((int)$style->alignment["textRotation"] > 90) {
1852                  $textRotation = 90 - (int)$style->alignment["textRotation"];
1853              }
1854  
1855              $docStyle->getAlignment()->setTextRotation(intval($textRotation));
1856              $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment["wrapText"]));
1857              $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment["shrinkToFit"]));
1858              $docStyle->getAlignment()->setIndent(intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0);
1859              $docStyle->getAlignment()->setReadorder(intval((string)$style->alignment["readingOrder"]) > 0 ? intval((string)$style->alignment["readingOrder"]) : 0);
1860          }
1861  
1862          // protection
1863          if (isset($style->protection)) {
1864              if (isset($style->protection['locked'])) {
1865                  if (self::boolean((string) $style->protection['locked'])) {
1866                      $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED);
1867                  } else {
1868                      $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED);
1869                  }
1870              }
1871  
1872              if (isset($style->protection['hidden'])) {
1873                  if (self::boolean((string) $style->protection['hidden'])) {
1874                      $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_PROTECTED);
1875                  } else {
1876                      $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED);
1877                  }
1878              }
1879          }
1880  
1881          // top-level style settings
1882          if (isset($style->quotePrefix)) {
1883              $docStyle->setQuotePrefix($style->quotePrefix);
1884          }
1885      }
1886  
1887      private static function readBorder($docBorder, $eleBorder)
1888      {
1889          if (isset($eleBorder["style"])) {
1890              $docBorder->setBorderStyle((string) $eleBorder["style"]);
1891          }
1892          if (isset($eleBorder->color)) {
1893              $docBorder->getColor()->setARGB(self::readColor($eleBorder->color));
1894          }
1895      }
1896  
1897      private function parseRichText($is = null)
1898      {
1899          $value = new PHPExcel_RichText();
1900  
1901          if (isset($is->t)) {
1902              $value->createText(PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $is->t));
1903          } else {
1904              if (is_object($is->r)) {
1905                  foreach ($is->r as $run) {
1906                      if (!isset($run->rPr)) {
1907                          $objText = $value->createText(PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $run->t));
1908  
1909                      } else {
1910                          $objText = $value->createTextRun(PHPExcel_Shared_String::ControlCharacterOOXML2PHP((string) $run->t));
1911  
1912                          if (isset($run->rPr->rFont["val"])) {
1913                              $objText->getFont()->setName((string) $run->rPr->rFont["val"]);
1914                          }
1915                          if (isset($run->rPr->sz["val"])) {
1916                              $objText->getFont()->setSize((string) $run->rPr->sz["val"]);
1917                          }
1918                          if (isset($run->rPr->color)) {
1919                              $objText->getFont()->setColor(new PHPExcel_Style_Color(self::readColor($run->rPr->color)));
1920                          }
1921                          if ((isset($run->rPr->b["val"]) && self::boolean((string) $run->rPr->b["val"])) ||
1922                              (isset($run->rPr->b) && !isset($run->rPr->b["val"]))) {
1923                              $objText->getFont()->setBold(true);
1924                          }
1925                          if ((isset($run->rPr->i["val"]) && self::boolean((string) $run->rPr->i["val"])) ||
1926                              (isset($run->rPr->i) && !isset($run->rPr->i["val"]))) {
1927                              $objText->getFont()->setItalic(true);
1928                          }
1929                          if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) {
1930                              $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]);
1931                              if ($vertAlign == 'superscript') {
1932                                  $objText->getFont()->setSuperScript(true);
1933                              }
1934                              if ($vertAlign == 'subscript') {
1935                                  $objText->getFont()->setSubScript(true);
1936                              }
1937                          }
1938                          if (isset($run->rPr->u) && !isset($run->rPr->u["val"])) {
1939                              $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE);
1940                          } elseif (isset($run->rPr->u) && isset($run->rPr->u["val"])) {
1941                              $objText->getFont()->setUnderline((string)$run->rPr->u["val"]);
1942                          }
1943                          if ((isset($run->rPr->strike["val"]) && self::boolean((string) $run->rPr->strike["val"])) ||
1944                              (isset($run->rPr->strike) && !isset($run->rPr->strike["val"]))) {
1945                              $objText->getFont()->setStrikethrough(true);
1946                          }
1947                      }
1948                  }
1949              }
1950          }
1951  
1952          return $value;
1953      }
1954  
1955      private function readRibbon($excel, $customUITarget, $zip)
1956      {
1957          $baseDir = dirname($customUITarget);
1958          $nameCustomUI = basename($customUITarget);
1959          // get the xml file (ribbon)
1960          $localRibbon = $this->getFromZipArchive($zip, $customUITarget);
1961          $customUIImagesNames = array();
1962          $customUIImagesBinaries = array();
1963          // something like customUI/_rels/customUI.xml.rels
1964          $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels';
1965          $dataRels = $this->getFromZipArchive($zip, $pathRels);
1966          if ($dataRels) {
1967              // exists and not empty if the ribbon have some pictures (other than internal MSO)
1968              $UIRels = simplexml_load_string($this->securityScan($dataRels), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions());
1969              if ($UIRels) {
1970                  // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image
1971                  foreach ($UIRels->Relationship as $ele) {
1972                      if ($ele["Type"] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1973                          // an image ?
1974                          $customUIImagesNames[(string) $ele['Id']] = (string)$ele['Target'];
1975                          $customUIImagesBinaries[(string)$ele['Target']] = $this->getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']);
1976                      }
1977                  }
1978              }
1979          }
1980          if ($localRibbon) {
1981              $excel->setRibbonXMLData($customUITarget, $localRibbon);
1982              if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) {
1983                  $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries);
1984              } else {
1985                  $excel->setRibbonBinObjects(null);
1986              }
1987          } else {
1988              $excel->setRibbonXMLData(null);
1989              $excel->setRibbonBinObjects(null);
1990          }
1991      }
1992  
1993      private static function getArrayItem($array, $key = 0)
1994      {
1995          return (isset($array[$key]) ? $array[$key] : null);
1996      }
1997  
1998      private static function dirAdd($base, $add)
1999      {
2000          return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
2001      }
2002  
2003      private static function toCSSArray($style)
2004      {
2005          $style = str_replace(array("\r","\n"), "", $style);
2006  
2007          $temp = explode(';', $style);
2008          $style = array();
2009          foreach ($temp as $item) {
2010              $item = explode(':', $item);
2011  
2012              if (strpos($item[1], 'px') !== false) {
2013                  $item[1] = str_replace('px', '', $item[1]);
2014              }
2015              if (strpos($item[1], 'pt') !== false) {
2016                  $item[1] = str_replace('pt', '', $item[1]);
2017                  $item[1] = PHPExcel_Shared_Font::fontSizeToPixels($item[1]);
2018              }
2019              if (strpos($item[1], 'in') !== false) {
2020                  $item[1] = str_replace('in', '', $item[1]);
2021                  $item[1] = PHPExcel_Shared_Font::inchSizeToPixels($item[1]);
2022              }
2023              if (strpos($item[1], 'cm') !== false) {
2024                  $item[1] = str_replace('cm', '', $item[1]);
2025                  $item[1] = PHPExcel_Shared_Font::centimeterSizeToPixels($item[1]);
2026              }
2027  
2028              $style[$item[0]] = $item[1];
2029          }
2030  
2031          return $style;
2032      }
2033  
2034      private static function boolean($value = null)
2035      {
2036          if (is_object($value)) {
2037              $value = (string) $value;
2038          }
2039          if (is_numeric($value)) {
2040              return (bool) $value;
2041          }
2042          return ($value === 'true' || $value === 'TRUE');
2043      }
2044  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1